类文件的常量池里写满了对别的类、方法、字段、字符串的引用,JVM 什么时候才去解析它们?缺一个类要到什么时候才会报错?这篇删掉类文件、打开类加载日志,逐个验证。
不带参数(分支不执行):
Main (已加载)
main 开始
Eager (已加载)
Eager 构造
main 结束
带参数(分支执行):
Main (已加载)
main 开始
Eager (已加载)
Eager 构造
Lazy (已加载)
Lazy.hi
main 结束 分支不执行时加载的类(源码里 Base 是父类 LazySub 的父类,Runnable 是 LazyImpl 的接口):
Main (已加载)
Base (已加载)
LazySub (已加载)
main 开始
main 结束
同样的程序加 -XX:+UnlockDiagnosticVMOptions -XX:-BytecodeVerificationRemote(不验证应用类)后加载的相关类:
Main (已加载)
main 开始
main 结束 不执行 new Gone() 时: 先不碰 Gone:main 正常运行到这里
执行 3 次 new Gone():
先不碰 Gone:main 正常运行到这里
第 1 次 make():java.lang.NoClassDefFoundError: Gone cause=java.lang.ClassNotFoundException: Gone 身份码 1735600054
第 2 次 make():java.lang.NoClassDefFoundError: Gone cause=java.lang.ClassNotFoundException: Gone 身份码 666988784
第 3 次 make():java.lang.NoClassDefFoundError: Gone cause=java.lang.ClassNotFoundException: Gone 身份码 1414644648 常量池条目数 76 ;各类型: {'Utf8': 43, 'Class': 11, 'NameAndType': 8, 'Methodref': 6, 'String': 3, 'InterfaceMethodref': 1, 'Fieldref': 1, 'InvokeDynamic': 1, 'Integer': 1, 'MethodHandle': 1}
常量池里的前 14 个引用类条目:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#7 = Class #8 // java/util/ArrayList
#9 = Methodref #7.#3 // java/util/ArrayList."<init>":()V
#10 = String #11 // x
#12 = InterfaceMethodref #13.#14 // java/util/List.add:(Ljava/lang/Object;)Z
#13 = Class #15 // java/util/List
#18 = Fieldref #19.#20 // java/lang/System.out:Ljava/io/PrintStream;
#19 = Class #21 // java/lang/System
#24 = Methodref #25.#26 // java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
#25 = Class #27 // java/lang/String
#30 = Methodref #31.#32 // java/lang/Math.max:(II)I
#31 = Class #33 // java/lang/Math
#36 = InvokeDynamic #0:#37 // #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
getstatic System.out / ldc / invokestatic Math.max 在字节码里: ['0: new #7 // class java/util/ArrayList', '9: ldc #10 // String x', '11: invokeinterface #12, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z', '17: getstatic #18 // Field java/lang/System.out:Ljava/io/PrintStream;', '21: invokestatic #24 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;', '24: iconst_1', '25: iconst_2', '26: invokestatic #30 // Method java/lang/Math.max:(II)I', '29: invokedynamic #36, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang', '34: invokevirtual #40 // Method java/io/PrintStream.println:(Ljava/lang/String;)V']同一个类里 "shared-literal" == 另一个类里的同一个字面量:true;new String == 字面量:false;z.intern() == 字面量:true;编译期拼接 "shared-" + "literal" == 字面量:true 运行时拼接 half + "literal" == 字面量:false;运行时拼接再 intern:true
加载的 Main 的 Lambda 类: 3
Main$$Lambda/0x0000008001000a08 source: Main
Main$$Lambda/0x0000008001000c28 source: Main
Main$$Lambda/0x0000008001001000 source: Main