虚拟机如何处理装载类失败的情况

simpleman7210 2013-09-10
如果虚拟机在装载一个类C的时候失败了,比如C没有找到,或者解析C的时候遇到格式或数据错误,或者C的super class没有找到或解析出错,那么,以后还会不会重新尝试装载C或者其super class呢?

举个例子,执行某些字节码指令,会触发对类的装载,比如new指令,getstatic, putstatic等,倘若在装载的过程中遇到错误,以后再执行到这样的指令时,会不会重新尝试装载呢?还是直接抛出错误(以前的解析错误被记录了)?虚拟机规范对此有没有什么说法或要求。

RednaxelaFX 2013-09-10
楼主的问题,一部分可以由用户定制,而一部分写死在VM里。

自定义ClassLoader如果覆写了loadClass()/findClass(),那么可以在里面自定义“找不到类”的情况下要不要记录在自己里面以便以后不重复加载。这个还没到JVM那层,所以JVM管不着。
但楼主想问的多半不是这个。

楼主关心的功能在这里:(JDK 6的HotSpot VM)
constantPoolOopDesc::klass_at_impl()
  // The original attempt to resolve this constant pool entry failed so find the
  // original error and throw it again (JVMS 5.4.3).
  if (in_error) {
    symbolOop error = SystemDictionary::find_resolution_error(this_oop, which);
    guarantee(error != (symbolOop)NULL, "tag mismatch with resolution error table");
    ResourceMark rm;
    // exception text will be the class name
    const char* className = this_oop->unresolved_klass_at(which)->as_C_string();
    THROW_MSG_0(error, className);
  }

也就是HotSpot VM是记录了resolution error的,在SystemDictionary里有个resolution_errors表;后面再尝试resolve的时候会把记录下来的异常抛出去。

对应的JVM规范规定是:http://docs.oracle.com/javase/specs/jvms/se5.0/html/ConstantPool.doc.html#73492
JVM Spec, 2nd Edition 写道
Subsequent attempts to resolve a symbolic reference that the Java virtual machine has previously unsuccessfully attempted to resolve always fails with the same error that was thrown as a result of the initial resolution attempt.


新版JVM规范里这部分规定还是在5.4.3:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4.3
simpleman7210 2013-09-10
谢谢指出来。原来JVM规范对此真有要求。
Global site tag (gtag.js) - Google Analytics