1、验证(Verify)
- 目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。
- 主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。
2、准备(Prepare)
package com.jvm.java;public class HelloApp {//在prepare:a=0 ---->initial:a=1private static int a = 1;public static void main(String[] args) {System.out.println(a);} }
- 为类变量分配内存并且设置该类变量的默认初始值,即零值。
- 这里不包括含有final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化;
- 这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
3、解析(Resolve)
- 将常量池内的符号引用转换为直接引用的过程。
- 事实上,解析操作往往会伴随着JVM在执行完初始化之后再执行。
- 符号引用就是一组符号来描述所引用的目标。符号引用的字面量形式明确定义在《java虚拟机规范》的Class文件格式中。直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。
- 解析动作主要针对类或接口、字段、类名称、接口方法、方法类型等。对应常量池中的CONSTANT_Class_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等。
3.1、反编译
PS F:\IdeaProjects\JavaSenior\out\production\Test\com\jvm\java> javap -v HelloApp.class Classfile /F:/IdeaProjects/JavaSenior/out/production/Test/com/jvm/java/HelloApp.classLast modified 2023-8-24; size 600 bytesMD5 checksum 5ed26a0b8b074c9a78dfa95afc3ae540Compiled from "HelloApp.java" public class com.jvm.java.HelloApp minor version: 0 major version: 61 flags: ACC_PUBLIC, ACC_SUPER Constant pool:#1 = Methodref #2.#3 // java/lang/Object."<init>":()V#2 = Class #4 // java/lang/Object#3 = NameAndType #5:#6 // "<init>":()V#4 = Utf8 java/lang/Object#5 = Utf8 <init>#6 = Utf8 ()V#7 = Fieldref #8.#9 // java/lang/System.out:Ljava/io/PrintStream;#8 = Class #10 // java/lang/System#9 = NameAndType #11:#12 // out:Ljava/io/PrintStream;#10 = Utf8 java/lang/System#11 = Utf8 out#12 = Utf8 Ljava/io/PrintStream;#13 = Fieldref #14.#15 // com/jvm/java/HelloApp.a:I#14 = Class #16 // com/jvm/java/HelloApp#15 = NameAndType #17:#18 // a:I#16 = Utf8 com/jvm/java/HelloApp#17 = Utf8 a#18 = Utf8 I#19 = Methodref #20.#21 // java/io/PrintStream.println:(I)V#20 = Class #22 // java/io/PrintStream#21 = NameAndType #23:#24 // println:(I)V#22 = Utf8 java/io/PrintStream#23 = Utf8 println#24 = Utf8 (I)V#25 = Utf8 Code#26 = Utf8 LineNumberTable#27 = Utf8 LocalVariableTable#28 = Utf8 this#29 = Utf8 Lcom/jvm/java/HelloApp;#30 = Utf8 main#31 = Utf8 ([Ljava/lang/String;)V#32 = Utf8 args#33 = Utf8 [Ljava/lang/String;#34 = Utf8 <clinit>#35 = Utf8 SourceFile#36 = Utf8 HelloApp.java {public com.jvm.java.HelloApp();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 3: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lcom/jvm/java/HelloApp;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;3: getstatic #13 // Field a:I6: invokevirtual #19 // Method java/io/PrintStream.println:(I)V9: returnStart Length Slot Name Signature0 10 0 args [Ljava/lang/String;static {};descriptor: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: iconst_11: putstatic #13 // Field a:I4: returnLineNumberTable:line 6: 0 } SourceFile: "HelloApp.java" PS F:\IdeaProjects\JavaSenior\out\production\Test\com\jvm\java>