查询java类文件的加载/链接/初始化阶段



下面是代码:

package packagename;
import java.lang.reflect.Method;
class Super{
    static{
        System.out.println("Super");
    }
    public void superMethod(){
    }
}
class Sub extends Super{
    static{
        System.out.println("Sub");
    }
    public void subMethod(){
    }
}
public class Example {
     static{
        System.out.println("In Example");
      }
     public static void main(String[] args){
        Class myClass = Sub.class;
        Method[] methods = myClass.getMethods();
        for(Method eachMethod :  methods){
            System.out.println(eachMethod.getName() + " with " + eachMethod.getParameterCount() + " parameters");
        }
    }
}

在编译和执行此代码时,

> java Example

class Example得到加载\链接\\初始化。当Java解释器开始解释class Examplemain()方法时,在计算表达式Sub.class并分配给Class myClass变量class Super&CCD_ 8被加载&已链接,但未初始化。这就是CCD_ 9&不执行class Sub,如下输出所示。

In Example
subMethod with 0 parameters
superMethod with 0 parameters
wait with 0 parameters
wait with 2 parameters
wait with 1 parameters
equals with 1 parameters
toString with 0 parameters
hashCode with 0 parameters
getClass with 0 parameters
notify with 0 parameters
notifyAll with 0 parameters

我对类ExampleSuper&Sub

参见JVMS§5.5

5.5初始化

类或接口的初始化包括执行其类或接口初始化方法(§2.9(

类或接口C只能作为以下结果进行初始化:

  • Java虚拟机指令new、getstatic、putstatic或invokestatic中任何一条引用C的指令(§new、§getstatic,§putstatic、§invokestatic(的执行。这些指令通过字段引用或方法引用直接或间接引用类或接口。

    在执行新指令时,如果引用的类尚未初始化,则对其进行初始化。

    在执行getstatic、putstatic或invokestatic指令时,如果声明解析字段或方法的类或接口尚未初始化,则该类或接口将被初始化。

  • java.lang.invoke.MethodHandle实例的第一次调用,该实例是第2类(REF_getStatic(、第4类(REF_putStatic(、第6类(REF_invokeStatic(或第8类(REF_newInvokeSpecial(的方法句柄解析(§5.4.3.5(的结果。这意味着,当为invokedynamic指令(§invokedynamics(调用引导方法时,引导方法的类被初始化,这是调用站点说明符的连续解析的一部分

  • 调用类库中的某些反射方法(§2.12(,例如,在class类或java.lang.reflect.包中

  • 如果C是一个类,则初始化它的一个子类。

  • 如果C是一个声明非抽象、非静态方法的接口,则是直接或间接实现C的类的初始化。

  • 如果C是一个类,则在Java虚拟机启动时将其指定为初始类(§5.2(

在初始化之前,必须链接类或接口,即验证、准备和可选地解析。

一般来说,行为有规范。如果你想了解细节,你可以考虑先学习《Java®语言规范》和《Java®虚拟机规范》,如果你不理解某个部分,就提出问题,然后指向提出问题的部分。

只有示例被初始化。Class Sub从常量池中检索

Constant pool:
   #1 = Methodref          #16.#39        //  java/lang/Object."<init>":()V
   #2 = Class              #40            //  Sub

以及来自主的相关代码

Code:
  stack=4, locals=4, args_size=1
     0: ldc_w         #2                  // class Sub
     3: astore_1      
     4: aload_1       
     5: invokevirtual #3                  // Method java/lang/Class.getMethods:()[Ljava/lang/reflect/Method;

因此,字节码证实了您的观察结果,即Sub没有初始化。执行代码时不需要。

相关内容

  • 没有找到相关文章

最新更新