JVM-学习

JVM 基础学习

ClassLoader SubSystem

  1. 类加载
  2. 类链接(验证,准备,解析)
  3. 初始化

加载

加载就是读取class文件,并在方法区存储对应的二进制数据,每一个class文件jvm会存储以下信息至方法区:

  1. 类(接口,枚举)的全限定名称
  2. 该类(接口,枚举)的直接父类的全限定名称
  3. class文件是否关联一个类(接口,枚举)
  4. 修饰符信息
  5. 局部变量,成员变量信息
  6. 方法信息
  7. 常量池信息等等

在加载class文件之后,jvm会立即创建一个代表该类的Class对象,以表示堆内存上的类级别的二进制信息.
每一个class文件加载之后只会创建一个代表该类的Class对象,无论你该类你在程序中使用多少次(创建多少次)

链接

  1. 验证

检查类的Class对象的二进制表示是否正确(静态约束和结构化约束),检查class文件是否符合规范,编译版本是否兼容.如果确认文件无误,可以使用jvm参数关闭验证.

  1. 准备

jvm分配静态变量内存空间(变量定义在方法区上,变量的值如果是引用类型则在堆空间,如果是原始类型直接分配在方法区上,值分配在初始化时候),并为静态变量(static)赋默认值(不是初始值,初始值在初始化阶段赋值),如果是类常量(final static)直接赋初始值

  1. 解析

将符号引用替换为直接引用(只会执行一次,这一步是可选的直到符号引用被使用).
符号引用:一组String字符串能唯一定位到所引用的类,变量或者方法.(当一个类编译完成,所有的方法引用,变量引用等等都是以符号引用保存在常量池中).
直接引用:直接指向目标的指针,相对偏移量(java做法),一个能定位到目标地址的句柄.

初始化

这个阶段所有的静态变量会被赋初始值,所有的静态代码块被执行(从上到下,从父类到子类),符合以下任意条件会初始化类:

  1. new 一个该对象
  2. 访问(读取或者设置)该类的静态字段或者调用该类的静态方法
  3. 反射
  4. 初始化类,会先初始化父类
  5. main方法主类,jvm会优先初始化

ClassLoader类型

  1. BootstrapClassLoader
    用c++实现,负责加载jdk->jre->lib->*.jar
  2. ExtensionClassLoader
    由sun.misc.Launcher$ExtClassLoader类实现,负责加载jdk->jre->lib->ext->*.class
  3. ApplicationClassLoader
    由sun.misc.Louncher$AppClassLoader实现,负责加载用户程序的类库(classpath下)

CLassLoader 使用双亲委派机制(delegation hierarchy principle): 当jvm遇到一个类,会先从方法区寻找该类的二进制表示,如果未找到如,则ClassLoader SubSystem会请求Application ClassLoader来加载这个这个类,ApplicationClassLoader会委托给ExtensionClassLoader加载,ExtensionClassLoader会委托给BootstrapClassLoader加载,当父加载器如果无法加载则会在委托给子的加载器加载.
ps: 这里的父子并不具有继承关系,只是上层加载器的引用.

运行时数据区域(Run-Time Data Areas)

Method area

方法区: AKA永久代(1.8之前),AKA MetaSpace(1.8之后);
jvm规范说方法区是逻辑上属于堆空间,可以是非连续性的,可以不需要垃圾回收机制,1.7方法区的实现是堆上的永久代,1.8之后方法区的实现变成了直接在本地内存上分配的元空间(MetaSpace,存储Class类的元数据)
jvm启动时候就创建,全局共享,它存储每个类的结构,运行时常量池,字段和方法数据,构造函数,包含特殊的初始化方法.
如果方法区中的内存无法满足分配请求,Java 虚拟机将抛出 OutOfMemoryError.

heap

堆: 在jvm启动时候创建,全局共享,堆是运行时数据区,从中分配所有类实例和数组的内存;垃圾回收机制主要是针对该区域回收.
1.7: 新生代,老年代,永久代.
1.8:新生代,老年代.
如果对象需要分配的内存比可回收的内存多,则抛出OutOfMemoryError.

stack

栈:每一个线程都有一个私有的栈,在线程创建时候被创建,栈里面存储着frame(stack frame),frame保存局部变量和部分结果(方法调用过程中产生),参与方法得调用和结果得返回.当一个方法被调用时候frame就会被创建,jvm对栈只有两个操作,psuh and pop
如果线程需要得栈空间大于虚拟机所允许的大小,则抛出StackOverflowError.
如果栈可以动态扩展,而扩展没有足够的内存空间,或者初始化一个新的线程栈时候没有足够的空间,则会抛出OutOfMemoryError.

Run-time Constant pool

运行时常量池:每个类或者接口一个,分配在方法区上.
包含
1.类,接口,方法,动态计算(lambda表达式)的符号引用–基本上等于对应类,接口,方法的全限定名称,但是会多出来一些额外的东西,虚拟机使用这些符号引用找到对应依赖的类.
2.类常量(final static)

如果创建类或者接口的运行时常量池需要的内存大于虚拟机可以使用的内存,则抛出OutOfMemoryError.

Frame

stack frame用于存储局部变量和中间结果以及执行动态链接,方法返回结果,抛出异常.以下简称frame
当一个方法被调用时会创建一个新的frame,当方法调用结束时候(无论正常结束还是异常结束),frame会被销毁.
在任何时候一个线程只会有一个frame被执行,被称作current frame,对应的是当前正在执行的方法.
当一个frame执行时候遇见调用另一个方法,会创建一个对应方法的new frame,new frame将成current frame,然后等待新的方法执行完成,new frame返回结果至之前的frame,然后之前的fram再次成为current frame并且丢弃new frame.

frame分为3个部分,局部变量数组,操作对象栈,帧数据

local variables

每一个frame中包含一个局部变量数组,数组的长度由编译期间方法内的代码确定,存储在class文件二进制的表示信息中(方法区中).
每个数组的槽站4个字节,其中int float reference占用数组的一个槽位,long double类型占用2个槽位,byte char short将会转会为int类型占用一个槽位,boolean类型占用的槽位不同虚拟机实现不同,大部分情况占用1个槽位.

operand stack

操作栈,也是一个栈类型的数据结构,先进后出; 作用是stack的工作空间work space, jvm指令从局部变量数组中获取数据push至操作栈,或者从操作栈中pop数据进行操作,然后在push结果到操作栈,

每个frame都包含一个指向运行时常量池中该frame所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接.
在类加载阶段中的解析阶段会将符号引用转为直接引用,这种转化也称为静态解析.另外的一部分将在运行时转化为直接引用,这部分称为动态链接.

Class 文件结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ClassFile {
u4 magic; //魔法数,固定的,0xCAFEBABE
u2 minor_version; //编译次版本,向下兼容
u2 major_version; //编译主版本, 向下兼容
u2 constant_pool_count; //常量池长度
cp_info constant_pool[constant_pool_count-1]; //静态常量池,运行时生成动态常量池,下标从1开始
u2 access_flags; //访问权限
u2 this_class; //常量池中的该类的引用的索引
u2 super_class; //0或者是常量池中的一个索引,如果是0表示是`Object`类,如果是索引表示父类在常量池中的索引
u2 interfaces_count; //实现接口的数量
u2 interfaces[interfaces_count];//接口数组
u2 fields_count; //总共字段的数量(类变量,成员变量)
field_info fields[fields_count];//字段数组
u2 methods_count; //方法数量
method_info methods[methods_count];//方法数组
u2 attributes_count; //属性数量
attribute_info attributes[attributes_count]; //属性数组,比较复杂
}

其中u代表字节,u1一个字节,u2两个字节
分析示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class TestClass {

private String s = "fffff";

private static String s2 ="xxxxxx";

private final String s1 = "fdasg";

private final int i = 1000001;

private int j;

public Thread thread;

public static void main(String...args){
TestClass tc = new TestClass();
tc.start();
}

public void start(){
int iiii = 135;
thread = new Thread(() -> {
int jjjj = iiii;
System.out.println(s1);
System.out.println(++jjjj);
});
thread.start();

}
}public class TestClass {

private String s = "fffff";

private static String s2 ="xxxxxx";

private final String s1 = "fdasg";

private final int i = 1000001;

private int j;

public Thread thread;

public static void main(String...args){
TestClass tc = new TestClass();
tc.start();
}

public void start(){
thread = new Thread(() -> System.out.println(s1));
thread.start();

}
}

编译之后的运行时常量池
这里Constant的意思不是指存储的是常量,而是说是不变的东西,也就是说类的方法,字段名称,字段的值都是编译期间可以知道的,所以这些东西是不变的,这些存储是以静态constant_pool存储(class文件的constant_pool),当jvm启动时候就会将静态的constant_pool转换为runtime constant_pool.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
> javap -v TestClass.class
Constant pool:
#1 = Methodref #21.#53 // java/lang/Object."<init>":()V
#2 = String #54 // fffff
#3 = Fieldref #8.#55 // com/interact/jugg/TestClass.s:Ljava/lang/String;
#4 = String #56 // fdasg
#5 = Fieldref #8.#57 // com/interact/jugg/TestClass.s1:Ljava/lang/String;
#6 = Integer 1000001
#7 = Fieldref #8.#58 // com/interact/jugg/TestClass.i:I
#8 = Class #59 // com/interact/jugg/TestClass
#9 = Methodref #8.#53 // com/interact/jugg/TestClass."<init>":()V
#10 = Methodref #8.#60 // com/interact/jugg/TestClass.start:()V
#11 = Class #61 // java/lang/Thread
#12 = InvokeDynamic #0:#66 // #0:run:(Lcom/interact/jugg/TestClass;I)Ljava/lang/Runnable;
#13 = Methodref #11.#67 // java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
#14 = Fieldref #8.#68 // com/interact/jugg/TestClass.thread:Ljava/lang/Thread;
#15 = Methodref #11.#60 // java/lang/Thread.start:()V
#16 = Fieldref #69.#70 // java/lang/System.out:Ljava/io/PrintStream;
#17 = Methodref #71.#72 // java/io/PrintStream.println:(Ljava/lang/String;)V
#18 = Methodref #71.#73 // java/io/PrintStream.println:(I)V
#19 = String #74 // xxxxxx
#20 = Fieldref #8.#75 // com/interact/jugg/TestClass.s2:Ljava/lang/String;
#21 = Class #76 // java/lang/Object
#22 = Utf8 s
#23 = Utf8 Ljava/lang/String;
#24 = Utf8 s2
#25 = Utf8 s1
#26 = Utf8 ConstantValue
#27 = Utf8 i
#28 = Utf8 I
#29 = Utf8 j
#30 = Utf8 thread
#31 = Utf8 Ljava/lang/Thread;
#32 = Utf8 <init>
#33 = Utf8 ()V
#34 = Utf8 Code
#35 = Utf8 LineNumberTable
#36 = Utf8 LocalVariableTable
#37 = Utf8 this
#38 = Utf8 Lcom/interact/jugg/TestClass;
#39 = Utf8 main
#40 = Utf8 ([Ljava/lang/String;)V
#41 = Utf8 args
#42 = Utf8 [Ljava/lang/String;
#43 = Utf8 tc
#44 = Utf8 MethodParameters
#45 = Utf8 start
#46 = Utf8 iiii
#47 = Utf8 lambda$start$0
#48 = Utf8 (I)V
#49 = Utf8 jjjj
#50 = Utf8 <clinit>
#51 = Utf8 SourceFile
#52 = Utf8 TestClass.java
#53 = NameAndType #32:#33 // "<init>":()V
#54 = Utf8 fffff
#55 = NameAndType #22:#23 // s:Ljava/lang/String;
#56 = Utf8 fdasg
#57 = NameAndType #25:#23 // s1:Ljava/lang/String;
#58 = NameAndType #27:#28 // i:I
#59 = Utf8 com/interact/jugg/TestClass
#60 = NameAndType #45:#33 // start:()V
#61 = Utf8 java/lang/Thread
#62 = Utf8 BootstrapMethods
#63 = MethodHandle 6:#77 // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#64 = MethodType #33 // ()V
#65 = MethodHandle 7:#78 // REF_invokeSpecial com/interact/jugg/TestClass.lambda$start$0:(I)V
#66 = NameAndType #79:#80 // run:(Lcom/interact/jugg/TestClass;I)Ljava/lang/Runnable;
#67 = NameAndType #32:#81 // "<init>":(Ljava/lang/Runnable;)V
#68 = NameAndType #30:#31 // thread:Ljava/lang/Thread;
#69 = Class #82 // java/lang/System
#70 = NameAndType #83:#84 // out:Ljava/io/PrintStream;
#71 = Class #85 // java/io/PrintStream
#72 = NameAndType #86:#87 // println:(Ljava/lang/String;)V
#73 = NameAndType #86:#48 // println:(I)V
#74 = Utf8 xxxxxx
#75 = NameAndType #24:#23 // s2:Ljava/lang/String;
#76 = Utf8 java/lang/Object
#77 = Methodref #88.#89 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#78 = Methodref #8.#90 // com/interact/jugg/TestClass.lambda$start$0:(I)V
#79 = Utf8 run
#80 = Utf8 (Lcom/interact/jugg/TestClass;I)Ljava/lang/Runnable;
#81 = Utf8 (Ljava/lang/Runnable;)V
#82 = Utf8 java/lang/System
#83 = Utf8 out
#84 = Utf8 Ljava/io/PrintStream;
#85 = Utf8 java/io/PrintStream
#86 = Utf8 println
#87 = Utf8 (Ljava/lang/String;)V
#88 = Class #91 // java/lang/invoke/LambdaMetafactory
#89 = NameAndType #92:#96 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#90 = NameAndType #47:#48 // lambda$start$0:(I)V
#91 = Utf8 java/lang/invoke/LambdaMetafactory
#92 = Utf8 metafactory
#93 = Class #98 // java/lang/invoke/MethodHandles$Lookup
#94 = Utf8 Lookup
#95 = Utf8 InnerClasses
#96 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#97 = Class #99 // java/lang/invoke/MethodHandles
#98 = Utf8 java/lang/invoke/MethodHandles$Lookup
#99 = Utf8 java/lang/invoke/MethodHandles
{
public java.lang.Thread thread;
descriptor: Ljava/lang/Thread;
flags: (0x0001) ACC_PUBLIC

public com.interact.jugg.TestClass();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String fffff
7: putfield #3 // Field s:Ljava/lang/String;
10: aload_0
11: ldc #4 // String fdasg
13: putfield #5 // Field s1:Ljava/lang/String;
16: aload_0
17: ldc #6 // int 1000001
19: putfield #7 // Field i:I
22: return
LineNumberTable:
line 6: 0
line 8: 4
line 12: 10
line 14: 16
LocalVariableTable:
Start Length Slot Name Signature
0 23 0 this Lcom/interact/jugg/TestClass;

public static void main(java.lang.String...);
descriptor: ([Ljava/lang/String;)V
flags: (0x0089) ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=2, locals=2, args_size=1
0: new #8 // class com/interact/jugg/TestClass
3: dup
4: invokespecial #9 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #10 // Method start:()V
12: return
LineNumberTable:
line 21: 0
line 22: 8
line 23: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 args [Ljava/lang/String;
8 5 1 tc Lcom/interact/jugg/TestClass;
MethodParameters:
Name Flags
args

public void start();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=5, locals=2, args_size=1
0: sipush 135
3: istore_1
4: aload_0
5: new #11 // class java/lang/Thread
8: dup
9: aload_0
10: iload_1
11: invokedynamic #12, 0 // InvokeDynamic #0:run:(Lcom/interact/jugg/TestClass;I)Ljava/lang/Runnable;
16: invokespecial #13 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
19: putfield #14 // Field thread:Ljava/lang/Thread;
22: aload_0
23: getfield #14 // Field thread:Ljava/lang/Thread;
26: invokevirtual #15 // Method java/lang/Thread.start:()V
29: return
LineNumberTable:
line 26: 0
line 27: 4
line 32: 22
line 34: 29
LocalVariableTable:
Start Length Slot Name Signature
0 30 0 this Lcom/interact/jugg/TestClass;
4 26 1 iiii I

static {};
descriptor: ()V
flags: (0x0008) ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: ldc #19 // String xxxxxx
2: putstatic #20 // Field s2:Ljava/lang/String;
5: return
LineNumberTable:
line 10: 0
}

十六进制字节码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
TestClass.class
00000000: cafe babe 0000 0037 0064 0a00 1500 3508 .......7.d....5.
00000010: 0036 0900 0800 3708 0038 0900 0800 3903 .6....7..8....9.
00000020: 000f 4241 0900 0800 3a07 003b 0a00 0800 ..BA....:..;....
00000030: 350a 0008 003c 0700 3d12 0000 0042 0a00 5....<..=....B..
00000040: 0b00 4309 0008 0044 0a00 0b00 3c09 0045 ..C....D....<..E
00000050: 0046 0a00 4700 480a 0047 0049 0800 4a09 .F..G.H..G.I..J.
00000060: 0008 004b 0700 4c01 0001 7301 0012 4c6a ...K..L...s...Lj
00000070: 6176 612f 6c61 6e67 2f53 7472 696e 673b ava/lang/String;
00000080: 0100 0273 3201 0002 7331 0100 0d43 6f6e ...s2...s1...Con
00000090: 7374 616e 7456 616c 7565 0100 0169 0100 stantValue...i..
000000a0: 0149 0100 016a 0100 0674 6872 6561 6401 .I...j...thread.
000000b0: 0012 4c6a 6176 612f 6c61 6e67 2f54 6872 ..Ljava/lang/Thr
000000c0: 6561 643b 0100 063c 696e 6974 3e01 0003 ead;...<init>...
000000d0: 2829 5601 0004 436f 6465 0100 0f4c 696e ()V...Code...Lin
000000e0: 654e 756d 6265 7254 6162 6c65 0100 124c eNumberTable...L
000000f0: 6f63 616c 5661 7269 6162 6c65 5461 626c ocalVariableTabl
00000100: 6501 0004 7468 6973 0100 1d4c 636f 6d2f e...this...Lcom/
00000110: 696e 7465 7261 6374 2f6a 7567 672f 5465 interact/jugg/Te
00000120: 7374 436c 6173 733b 0100 046d 6169 6e01 stClass;...main.
00000130: 0016 285b 4c6a 6176 612f 6c61 6e67 2f53 ..([Ljava/lang/S
00000140: 7472 696e 673b 2956 0100 0461 7267 7301 tring;)V...args.
00000150: 0013 5b4c 6a61 7661 2f6c 616e 672f 5374 ..[Ljava/lang/St
00000160: 7269 6e67 3b01 0002 7463 0100 104d 6574 ring;...tc...Met
00000170: 686f 6450 6172 616d 6574 6572 7301 0005 hodParameters...
00000180: 7374 6172 7401 0004 6969 6969 0100 0e6c start...iiii...l
00000190: 616d 6264 6124 7374 6172 7424 3001 0004 ambda$start$0...
000001a0: 2849 2956 0100 046a 6a6a 6a01 0008 3c63 (I)V...jjjj...<c
000001b0: 6c69 6e69 743e 0100 0a53 6f75 7263 6546 linit>...SourceF
000001c0: 696c 6501 000e 5465 7374 436c 6173 732e ile...TestClass.
000001d0: 6a61 7661 0c00 2000 2101 0005 6666 6666 java.. .!...ffff
000001e0: 660c 0016 0017 0100 0566 6461 7367 0c00 f........fdasg..
000001f0: 1900 170c 001b 001c 0100 1b63 6f6d 2f69 ...........com/i
00000200: 6e74 6572 6163 742f 6a75 6767 2f54 6573 nteract/jugg/Tes
00000210: 7443 6c61 7373 0c00 2d00 2101 0010 6a61 tClass..-.!...ja
00000220: 7661 2f6c 616e 672f 5468 7265 6164 0100 va/lang/Thread..
00000230: 1042 6f6f 7473 7472 6170 4d65 7468 6f64 .BootstrapMethod
00000240: 730f 0600 4d10 0021 0f07 004e 0c00 4f00 s...M..!...N..O.
00000250: 500c 0020 0051 0c00 1e00 1f07 0052 0c00 P.. .Q.......R..
00000260: 5300 5407 0055 0c00 5600 570c 0056 0030 S.T..U..V.W..V.0
00000270: 0100 0678 7878 7878 780c 0018 0017 0100 ...xxxxxx.......
00000280: 106a 6176 612f 6c61 6e67 2f4f 626a 6563 .java/lang/Objec
00000290: 740a 0058 0059 0a00 0800 5a01 0003 7275 t..X.Y....Z...ru
000002a0: 6e01 0034 284c 636f 6d2f 696e 7465 7261 n..4(Lcom/intera
000002b0: 6374 2f6a 7567 672f 5465 7374 436c 6173 ct/jugg/TestClas
000002c0: 733b 4929 4c6a 6176 612f 6c61 6e67 2f52 s;I)Ljava/lang/R
000002d0: 756e 6e61 626c 653b 0100 1728 4c6a 6176 unnable;...(Ljav
000002e0: 612f 6c61 6e67 2f52 756e 6e61 626c 653b a/lang/Runnable;
000002f0: 2956 0100 106a 6176 612f 6c61 6e67 2f53 )V...java/lang/S
00000300: 7973 7465 6d01 0003 6f75 7401 0015 4c6a ystem...out...Lj
00000310: 6176 612f 696f 2f50 7269 6e74 5374 7265 ava/io/PrintStre
00000320: 616d 3b01 0013 6a61 7661 2f69 6f2f 5072 am;...java/io/Pr
00000330: 696e 7453 7472 6561 6d01 0007 7072 696e intStream...prin
00000340: 746c 6e01 0015 284c 6a61 7661 2f6c 616e tln...(Ljava/lan
00000350: 672f 5374 7269 6e67 3b29 5607 005b 0c00 g/String;)V..[..
00000360: 5c00 600c 002f 0030 0100 226a 6176 612f \.`../.0.."java/
00000370: 6c61 6e67 2f69 6e76 6f6b 652f 4c61 6d62 lang/invoke/Lamb
00000380: 6461 4d65 7461 6661 6374 6f72 7901 000b daMetafactory...
00000390: 6d65 7461 6661 6374 6f72 7907 0062 0100 metafactory..b..
000003a0: 064c 6f6f 6b75 7001 000c 496e 6e65 7243 .Lookup...InnerC
000003b0: 6c61 7373 6573 0100 cc28 4c6a 6176 612f lasses...(Ljava/
000003c0: 6c61 6e67 2f69 6e76 6f6b 652f 4d65 7468 lang/invoke/Meth
000003d0: 6f64 4861 6e64 6c65 7324 4c6f 6f6b 7570 odHandles$Lookup
000003e0: 3b4c 6a61 7661 2f6c 616e 672f 5374 7269 ;Ljava/lang/Stri
000003f0: 6e67 3b4c 6a61 7661 2f6c 616e 672f 696e ng;Ljava/lang/in
00000400: 766f 6b65 2f4d 6574 686f 6454 7970 653b voke/MethodType;
00000410: 4c6a 6176 612f 6c61 6e67 2f69 6e76 6f6b Ljava/lang/invok
00000420: 652f 4d65 7468 6f64 5479 7065 3b4c 6a61 e/MethodType;Lja
00000430: 7661 2f6c 616e 672f 696e 766f 6b65 2f4d va/lang/invoke/M
00000440: 6574 686f 6448 616e 646c 653b 4c6a 6176 ethodHandle;Ljav
00000450: 612f 6c61 6e67 2f69 6e76 6f6b 652f 4d65 a/lang/invoke/Me
00000460: 7468 6f64 5479 7065 3b29 4c6a 6176 612f thodType;)Ljava/
00000470: 6c61 6e67 2f69 6e76 6f6b 652f 4361 6c6c lang/invoke/Call
00000480: 5369 7465 3b07 0063 0100 256a 6176 612f Site;..c..%java/
00000490: 6c61 6e67 2f69 6e76 6f6b 652f 4d65 7468 lang/invoke/Meth
000004a0: 6f64 4861 6e64 6c65 7324 4c6f 6f6b 7570 odHandles$Lookup
000004b0: 0100 1e6a 6176 612f 6c61 6e67 2f69 6e76 ...java/lang/inv
000004c0: 6f6b 652f 4d65 7468 6f64 4861 6e64 6c65 oke/MethodHandle
000004d0: 7300 2100 0800 1500 0000 0600 0200 1600 s.!.............
000004e0: 1700 0000 0a00 1800 1700 0000 1200 1900 ................
000004f0: 1700 0100 1a00 0000 0200 0400 1200 1b00 ................
00000500: 1c00 0100 1a00 0000 0200 0600 0200 1d00 ................
00000510: 1c00 0000 0100 1e00 1f00 0000 0500 0100 ................
00000520: 2000 2100 0100 2200 0000 4d00 0200 0100 .!..."...M.....
00000530: 0000 172a b700 012a 1202 b500 032a 1204 ...*...*.....*..
00000540: b500 052a 1206 b500 07b1 0000 0002 0023 ...*...........#
00000550: 0000 0012 0004 0000 0006 0004 0008 000a ................
00000560: 000c 0010 000e 0024 0000 000c 0001 0000 .......$........
00000570: 0017 0025 0026 0000 0089 0027 0028 0002 ...%.&.....'.(..
00000580: 0022 0000 0049 0002 0002 0000 000d bb00 ."...I..........
00000590: 0859 b700 094c 2bb6 000a b100 0000 0200 .Y...L+.........
000005a0: 2300 0000 0e00 0300 0000 1500 0800 1600 #...............
000005b0: 0c00 1700 2400 0000 1600 0200 0000 0d00 ....$...........
000005c0: 2900 2a00 0000 0800 0500 2b00 2600 0100 ).*.......+.&...
000005d0: 2c00 0000 0501 0029 0000 0001 002d 0021 ,......).....-.!
000005e0: 0001 0022 0000 005e 0005 0002 0000 001e ..."...^........
000005f0: 1100 873c 2abb 000b 592a 1bba 000c 0000 ...<*...Y*......
00000600: b700 0db5 000e 2ab4 000e b600 0fb1 0000 ......*.........
00000610: 0002 0023 0000 0012 0004 0000 001a 0004 ...#............
00000620: 001b 0016 0020 001d 0022 0024 0000 0016 ..... ...".$....
00000630: 0002 0000 001e 0025 0026 0000 0004 001a .......%.&......
00000640: 002e 001c 0001 1002 002f 0030 0001 0022 ........./.0..."
00000650: 0000 005f 0002 0003 0000 0015 1b3d b200 ..._.........=..
00000660: 1012 04b6 0011 b200 1084 0201 1cb6 0012 ................
00000670: b100 0000 0200 2300 0000 1200 0400 0000 ......#.........
00000680: 1c00 0200 1d00 0a00 1e00 1400 1f00 2400 ..............$.
00000690: 0000 2000 0300 0000 1500 2500 2600 0000 .. .......%.&...
000006a0: 0000 1500 2e00 1c00 0100 0200 1300 3100 ..............1.
000006b0: 1c00 0200 0800 3200 2100 0100 2200 0000 ......2.!..."...
000006c0: 1e00 0100 0000 0000 0612 13b3 0014 b100 ................
000006d0: 0000 0100 2300 0000 0600 0100 0000 0a00 ....#...........
000006e0: 0300 3300 0000 0200 3400 5f00 0000 0a00 ..3.....4._.....
000006f0: 0100 5d00 6100 5e00 1900 3e00 0000 0c00 ..].a.^...>.....
00000700: 0100 3f00 0300 4000 4100 400a ..?...@.A.@.

1.cafebabe固定4个字节
2.0000 次版本,无
3.0037 主版本,对应十进制为55,查找版本对照表,为11,具体规则可以查看jvm规范,无非就是什么版本对应什么数字,哪些版本没有次要版本,做了什么兼容设定
4.0064 常量池长度,对应十进制为100,上面常量池示例中正好到序号99.
5.0a 对应常量池第一个变量,cp_info具体结构为:

1
2
3
4
5
cp_info {
u1 tag;
u1 info[];
}

所以第一个字符0a对用为10,10对应的cp_infotagMethod_ref,对应结构如下:

1
2
3
4
5
CONSTANT_Methodref_info {
u1 tag;
u2 class_index;
u2 name_and_type_index;
}

所以随后的两个字节0015代表着对应的class在常量池中的索引,0015对应的十进制为21,查看上面javap代码可以找到对应#21为java.lang.Object类.
在之后的2个字节0035代表着也对应着常量池中的索引,而该索引处的数据结构必须符合CONSTANT_NameAndType_info,0035对应十进制为53,查看上面javap代码,得到#53是一个NameAndType而且按照对应的结构引用了utf_8结构的#32#33,分别为特殊方法<init>以及返回值()v,世界上就是一个初始化方法.
上述分析对比一下javap反编代码的常量池#1,符合我们的分析.

静态常量池中的CONSTANT_NameAndType_info, CONSTANT_Module_info, and CONSTANT_Package_info, and the foundational structure CONSTANT_Utf8_info不会被转换至动态常量池中,这些结构只会在初始化实例时候间接的使用

后记

简单的jvm入门是完成了,虽然看懂了,但是不知道又什么用,参考了很多文章和书籍,jvm规范是最权威的,但是写的略简单,而博客文章又是千篇一律,互相抄,所以最后总结还是看书加动手实践是最好的.