Skip to content

Commit 6609dca

Browse files
committed
Linking(链接)阶段
1 parent 3454288 commit 6609dca

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

JVM/浓缩版/2.类的加载篇/1.类的加载过程(生命周期).md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,105 @@
6060

6161
加载的类在JVM中创建相应的类结构,类结构会存储在方法区(JDK1.8之前:永久代;JDK1.8及之后:元空间)。
6262

63+
### Class实例的位置在哪
64+
65+
**Class实例的位置**
66+
67+
类将.class文件加载至元空间后,会在堆中创建一个Java.lang.Class对象,用来封装类位于方法区内的数据结构,该Class对象是在加载类的过程中创建的,每个类都对应有一个Class类型的对象。(instanceKlass --> mirror :Class的实例)
68+
69+
图示
70+
71+
![](images/3.Class类型对象.jpeg)
72+
73+
外部可以通过访问代表Order类的Class对象来获取Order的类数据结构。
74+
75+
**再说明**
76+
77+
Class类的构造方法是私有的,只有JVM能够创建。
78+
79+
java.lang.Class实例是访问类型元数据的接口,也是实现反射的关键数据、入口。通过Class类提供的接口,可以获得目标类所关联的.class文件中具体的数据结构:方法、字段等信息。
80+
81+
## 过程二:Linking(链接)阶段
82+
83+
### 环节1:链接阶段之Verification(验证)
84+
85+
当类加载到系统后,就开始链接操作,验证是链接操作的第一步。
86+
87+
<font color = 'red'>它的目的是保证加载的字节码是合法、合理并符合规范的。</font>
88+
89+
验证的步骤比较复杂,实际要验证的项目也很繁多,大体上Java虚拟机需要做以下检査,如图所示。
90+
91+
![](images/4.链接阶段之Verification(验证).jpeg)
92+
93+
**整体说明:**
94+
95+
验证的内容则涵盖了类数据信息的格式验证、语义检查、字节码验证,以及符号引用验证等。
96+
97+
- 其<font color = 'red'>中格式验证会和装载阶段一起执行。</font>验证通过之后,类加载器才会成功将类的二进制数据信息加载到方法区中。
98+
- <font color = 'red'>格式验证之外的验证操作将会在方法区中进行。</font>
99+
100+
具体说明:
101+
1. 格式验证:是否以魔数 OxCAFEBABE开头,主版本和副版本号是否在当前Java虚拟机的支持范围内,数据中每一个项是否都拥有正确的长度等。
102+
103+
2. Java虚拟机会进行字节码的语义检查,但凡在语义上不符合规范的,虚拟机也不会给予验证通过。比如:
104+
105+
- 是否所有的类都有父类的存在(在Java里,除了Object外,其他类都应该有父类)
106+
- 是否一些被定义为final的方法或者类被重写或继承了
107+
- 非抽象类是否实现了所有抽象方法或者接口方法
108+
- 是否存在不兼容的方法(比如方法的签名除了返回值不同,其他都一样,这种方法会让虚拟机无从下手调度;abstract情况下的方法,就不能是final的了)
109+
110+
3. Java虚拟机还会进行字节码验证,字节码验证也是验证过程中最为复杂的一个过程。它试图通过对字节码流的分析,判断字节码是否可以被正确地执行。比如:
111+
112+
- 在字节码的执行过程中,是否会跳转到一条不存在的指令
113+
- 函数的调用是否传递了正确类型的参数
114+
- 变量的赋值是不是给了正确的数据类型等
115+
116+
栈映射帧(StackMapTable)就是在这个阶段,用于检测在特定的字节码处,其局部变量表和操作数栈是否有着正确的数据类型。但遗憾的是,100%准确地判断一段字节码是否可以被安全执行是无法实现的,因此,该过程只是尽可能地检査出可以预知的明显的问题。<font color = 'red'>如果在这个阶段无法通过检查,虚拟机也不会正确装载这个类。但是,如果通过了这个阶段的检查,也不能说明这个类是完全没有问题的。</font>
117+
118+
在前面3次检查中,已经排除了文件格式错误、语义错误以及字节码的不正确性。但是依然不能确保类是没有问题的。
119+
120+
4. 校验器还将进行符号引用的验证。Class文件在其常量池会通过字符串记录自己将要使用的其他类或者方法。因此,在验证阶段,虚拟机就会检查这些类或者方法确实是存在的,并且当前类有权限访问这些数据,如果一个需要使用类无法在系统中找到,则会抛出NoClassDefFoundError,如果一个方法无法被找到,则会抛出NoSuchMethodError。
121+
122+
<font color = 'red'>此阶段在解析环节才会执行。</font>
123+
124+
### 环节2:链接阶段之Preparation(准备)
125+
126+
<font color = 'red'>简言之,为类的静态变量分配内存,并将其初始化为</font><font color = 'orange'>默认值。</font>
127+
128+
在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置默认初始值。Java虚拟机为各类型变量默认的初始值如表所示。
129+
130+
![](images/5.初始值.jpeg)
131+
132+
注意:Java并不支持boolean类型,对于boolean类型,内部实现是int,由于int的默认值是0,故对应的,boolean的默认值就是false。
133+
134+
注意:
135+
1. <font color = 'red'>这里不包含基本数据类型的字段用static final修饰的情况,因为final在编译的时候就会分配了,准备阶段会显式赋值。</font>
136+
2. 注意这里不会为实例变量分配初始化,实例变量是会随着对象一起分配到Java堆中。
137+
3. <font color = 'red'>在这个阶段并不会像初始化阶段中那样会有初始化或者代码被执行。</font>
138+
139+
### 环节3:链接阶段之Resolution(解析)
140+
141+
<font color = 'red'>简言之,将类、接口、字段和方法的符号引用转为直接引用。</font>
142+
143+
所谓解析就是将符号引用转为直接引用,也就是得到类、字段、方法在内存中的指针或者偏移量。因此,可以说,如果直接引用存在,那么可以肯定系统中存在该类、方法或者字段。但只存在符号引用,不能确定系统中一定存在该结构。
144+
145+
146+
147+
148+
149+
150+
63151

152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
163+
164+

0 commit comments

Comments
 (0)