所属文集:ClassLoader串烧
类加载的过程
- 1.加载 : 查找并加载类的二进制表示,并由此二进制表示来创建类或接口的过程。
- 2.链接 : 为了让类/接口可被jvm执行,而将类/接口并入虚拟机运行时状态的过程.
2.1 验证:确保被加载的类的正确性。
2.2 准备:为类的静态变量分配内存,并将其初始化为默认值,不会执行任何 Java 代码。
2.3 解析:把类中的 符号引用 转换为直接引用 - 3.初始化:执行类/接口的初始化方法 <clinit> ,为类变量赋初始值
- 4.使用
- 5.卸载
这个过程在Inside the Java Virtual Machine 深入java虚拟机的第三章从安全的角度,有比较全面通俗的 讲解。
原文:https://blog.csdn.net/biaobiaoqi/article/details/6909141
加载(Loading)
按如下三步执行
1.通过类的全名产生对应类的二进制数据流。(注意,如果没找到对应类文件,只有在类实际使用时才抛出错误。)
2.分析并将这些二进制数据流转换为方法区(JVM 的架构:方法区、堆,栈,本地方法栈,pc 寄存器)特定的数据结构(这些数据结构是实现有关的,不同 JVM 有不同实现)。这里处理了部分检验,比如类文件的魔数的验证,检查文件是否过长或者过短,确定是否有父类(除了 Obect 类)。
3.创建对应类的 java.lang.Class 对象实例,封装了类在方法区内的数据结构并且给程序员提供了访问方法区内的结构的接口,这就是反射的依赖基础(注意,有了对应的 Class 实例,并不意味着这个类已经完成了加载链链接!)。
链接(Linking)
链接的过程比加载过成复杂不少,这是实现 Java 的动态性的重要一步。分为三部分:验证,准备和解析。
-
1.验证(verification)
链接的第三部解析会把类中成员方法、成员变量、类和接口的符号引用替换为直接引用,而在这之前,需要检测被引用的类型正确性和接入属性是否正确(就是 public ,private 的的问题),诸如检查 final class 又没有被继承,检查静态变量的正确性等等。(注意到实际上有一部分验证过程已经在加载的过程中执行了。)
-
2.准备(preparation)
对类的成员变量分配空间。虽然有初始值,但这个时候不会对他们进行初始化(因为这里不会执行任何 Java 代码)。具体如下:
所有原始类型的值都为 0。如 float: 0f, int: 0, boolean: 0(注意 boolean 底层实现大多使用 int),引用类型则为 null。值得注意的是,JVM 可能会在这个时期给一些有助于程序运行效率提高的数据结构分配空间。比如方发表(类似与 C++中的虚函数表,参见另一篇博文《Java:方法的虚分派和方法表》)。
-
3.解析(Resolution)
为类、接口、方法、成员变量的符号引用定位直接引用(如果符号引用先到常量池中寻找符号,再找先应的类型,无疑会耗费更多时间),完成内存结构的布局。
这一步是可选的。可以在符号引用第一次被使用时完成,即所谓的延迟解析(late resolution)。但对用户而言,这一步永远是延迟解析的,即使运行时会执行 early resolution,但程序不会显示的在第一次判断出错误时抛出错误,而会在对应的类第一次主动使用的时候抛出错误!
另外,这一步与之后的类初始化是不冲突的,并非一定要所有的解析结束以后才执行类的初始化。不同的 JVM 实现不同。
初始化类(Initialization)
[初始化](https://www.jianshu.com/p/bd808f5ed3a6
《Java 类加载的延迟初始化》。
类的卸载
- jvm自带的类加载器所加载的类,在jvm的生命周期中,始终不会被卸载。
- 用户自定义的类加载器所加载的类是可以被卸载的。
vm参数: XX:+TraceClassUnloading
作用:跟踪jvm中类的 卸载,idea中设置了没看到效果求指导。。
java虚拟机结束生命周期
- 执行了System.exit()方法。
- 程序正常的结束。
- 程序在执行过程中遇到了异常或错误,导致异常终止。
- 由于操作系统出现错误,导致java虚拟机进程终止。
网友评论