CrazyDailyQuestion
CrazyDailyQuestion copied to clipboard
2019-10-23: 请谈谈Java的类加载过程?
Java
类加载过程完整生命周期分为:
-
load
-
加载
Class
- 通过
Class
全限定名获取二进制字节流 - 将
Class
文件加载到方法区 - 在内存中生成
java.lang.Class
表示这个Class
- 通过
-
获取
Class
- 从
zip
中获取,如: 从jar
,war
,ear
等格式的文件中读取Class
文件内容。 - 从网络获取,如:
Applet
- 动态生成,如:
动态代理
,ASM
框架等都是这种形式 - 由其他文件生成,典型的是从
ASP
中生成相应的Class
- 从
-
-
verify: 验证一个
class
文件是否合法,主要包括以下三个阶段-
文件格式验证
- 确保文件格式符合
Class
文件格式规范,如:验证魔数
,版本号
。
- 确保文件格式符合
-
元数据验证
- 确保
Class
的语义描述符合Java
的Class
规范,如:该Class
是否有父类。
- 确保
-
字节码验证
- 通过分析数据流和控制流,确保语义符合逻辑,如:验证类型转换是否合法。
-
符号引用验证
- 验证引用的类,成员变量,方法是否被访问,当前类是否存在相应的方法,成员等
-
-
prepare
public static int a = 123;
在准备阶段后,a
在内存中的值仍然为0,赋值 123
这个操作会在中初始化阶段执行,因此在初始化阶段产生对应的Class
对象才是123
。
- resolve
解析阶段,虚拟机会将常量池中的符号替换为直接引用,解析针对的是类,接口,方法,成员变量等符号引用。在转变成直接引用后,会触发校验阶段的符号引用验证,验证转换之后的直接引用是否能找到对应的类,方法,成员变量等,这里的可见类加载在各个阶段实际过程中可能是交错执行。
- init
public class Singleton {
public static final INSTANCE = new Singleton();
private Singleton() {
}
}
- use
- unlod
楼上说的很好,那我说下 一个对象实例化过程吧 例如:zi p = new zi();
- JVM会读取指定的路径下的zi.class文件,并加载进内存, 并会先加载zi的父类(如果有直接的父类的情况下).
- 在堆内存中的开辟空间,分配地址。
- 并在对象空间中,对对象中的属性进行默认初始化。
- 调用对应的构造函数进行初始化。
- 在构造函数中,第一行会先到调用父类中构造函数进行初始化。
- 父类初始化完毕后,在对子类的属性进行显示初始化。
- 在进行子类构造函数的特定初始化。
- 初始化完毕后,将地址值赋值给引用变量.