彻底剖析JVM类加载机制

java代码

public class Math { public static final int initData = 666; public static User user = new User(); public int compute() { int a = 1; int b = 2; int c = (a + b) * 10; return c; } public static void main(String[] args) { Math math = new Math(); math.compute(); System.out.println("end"); } }

javac 编译,javap -v -p 查看class文件

Classfile /F:/workspace/advanced-java/target/classes/com/lzp/java/jvm/classloader/Math.class // 第1部分,描述信息:大小、修改时间、md5值等 Last modified 2022年1月8日; size 1006 bytes MD5 checksum 4cece4543963b23a98cd219a59c1887c Compiled from "Math.java" // 第2部分,描述信息:编译版本 public class com.lzp.java.jvm.classloader.Math minor version: 0 major version: 52 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #2 // com/lzp/java/jvm/classloader/Math super_class: #11 // java/lang/Object interfaces: 0, fields: 2, methods: 4, attributes: 1 // 第3部分,常量池信息 Constant pool: #1 = Methodref #11.#39 // java/lang/Object."<init>":()V #2 = Class #40 // com/lzp/java/jvm/classloader/Math #3 = Methodref #2.#39 // com/lzp/java/jvm/classloader/Math."<init>":()V #4 = Methodref #2.#41 // com/lzp/java/jvm/classloader/Math.compute:()I #5 = Fieldref #42.#43 // java/lang/System.out:Ljava/io/PrintStream; #6 = String #44 // end #7 = Methodref #45.#46 // java/io/PrintStream.println:(Ljava/lang/String;)V #8 = Class #47 // com/lzp/java/jvm/classloader/User #9 = Methodref #8.#39 // com/lzp/java/jvm/classloader/User."<init>":()V #10 = Fieldref #2.#48 // com/lzp/java/jvm/classloader/Math.user:Lcom/lzp/java/jvm/classloader/User; #11 = Class #49 // java/lang/Object #12 = Utf8 initData #13 = Utf8 I #14 = Utf8 ConstantValue #15 = Integer 666 #16 = Utf8 user #17 = Utf8 Lcom/lzp/java/jvm/classloader/User; #18 = Utf8 <init> #19 = Utf8 ()V #20 = Utf8 Code #21 = Utf8 LineNumberTable #22 = Utf8 LocalVariableTable #23 = Utf8 this #24 = Utf8 Lcom/lzp/java/jvm/classloader/Math; #25 = Utf8 compute #26 = Utf8 ()I #27 = Utf8 a #28 = Utf8 b #29 = Utf8 c #30 = Utf8 main #31 = Utf8 ([Ljava/lang/String;)V #32 = Utf8 args #33 = Utf8 [Ljava/lang/String; #34 = Utf8 math #35 = Utf8 MethodParameters #36 = Utf8 <clinit> #37 = Utf8 SourceFile #38 = Utf8 Math.java #39 = NameAndType #18:#19 // "<init>":()V #40 = Utf8 com/lzp/java/jvm/classloader/Math #41 = NameAndType #25:#26 // compute:()I #42 = Class #50 // java/lang/System #43 = NameAndType #51:#52 // out:Ljava/io/PrintStream; #44 = Utf8 end #45 = Class #53 // java/io/PrintStream #46 = NameAndType #54:#55 // println:(Ljava/lang/String;)V #47 = Utf8 com/lzp/java/jvm/classloader/User #48 = NameAndType #16:#17 // user:Lcom/lzp/java/jvm/classloader/User; #49 = Utf8 java/lang/Object #50 = Utf8 java/lang/System #51 = Utf8 out #52 = Utf8 Ljava/io/PrintStream; #53 = Utf8 java/io/PrintStream #54 = Utf8 println #55 = Utf8 (Ljava/lang/String;)V { // 第四部分,变量信息 public static final int initData; descriptor: I flags: (0x0019) ACC_PUBLIC, ACC_STATIC, ACC_FINAL ConstantValue: int 666 public static com.lzp.java.jvm.classloader.User user; descriptor: Lcom/lzp/java/jvm/classloader/User; flags: (0x0009) ACC_PUBLIC, ACC_STATIC public com.lzp.java.jvm.classloader.Math(); descriptor: ()V flags: (0x0001) ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Lcom/lzp/java/jvm/classloader/Math; // 第五部分,方法信息 public int compute(); descriptor: ()I flags: (0x0001) ACC_PUBLIC Code: stack=2, locals=4, args_size=1 0: iconst_1 1: istore_1 2: iconst_2 3: istore_2 4: iload_1 5: iload_2 6: iadd 7: bipush 10 9: imul 10: istore_3 11: iload_3 12: ireturn LineNumberTable: line 9: 0 line 10: 2 line 11: 4 line 12: 11 LocalVariableTable: Start Length Slot Name Signature 0 13 0 this Lcom/lzp/java/jvm/classloader/Math; 2 11 1 a I 4 9 2 b I 11 2 3 c I public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: new #2 // class com/lzp/java/jvm/classloader/Math 3: dup 4: invokespecial #3 // Method "<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4 // Method compute:()I 12: pop 13: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 16: ldc #6 // String end 18: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 21: return LineNumberTable: line 16: 0 line 17: 8 line 18: 13 line 19: 21 LocalVariableTable: Start Length Slot Name Signature 0 22 0 args [Ljava/lang/String; 8 14 1 math Lcom/lzp/java/jvm/classloader/Math; MethodParameters: Name Flags args static {}; descriptor: ()V flags: (0x0008) ACC_STATIC Code: stack=2, locals=0, args_size=0 0: new #8 // class com/lzp/java/jvm/classloader/User 3: dup 4: invokespecial #9 // Method com/lzp/java/jvm/classloader/User."<init>":()V 7: putstatic #10 // Field user:Lcom/lzp/java/jvm/classloader/User; 10: return LineNumberTable: line 6: 0 }

方法中的#1/2,可以到ConstantPool找到对应符号。

参考字节码指令表:https://docs.oracle.com/javase/specs/jvms/se8/html/index.html。

1 类加载过程

j经典的类加载过程如下图,包括加载、链接、初始化三部分。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgxjzg.html