diff --git a/docs/java/jvm/类加载过程.md b/docs/java/jvm/类加载过程.md index 895ba43f..6c41bbb6 100644 --- a/docs/java/jvm/类加载过程.md +++ b/docs/java/jvm/类加载过程.md @@ -8,20 +8,27 @@ - [准备](#准备) - [解析](#解析) - [初始化](#初始化) + - [扩展:类的生命周期](#扩展:类的生命周期) > 公众号JavaGuide 后台回复关键字“1”,免费获取JavaGuide配套的Java工程师必备学习资源(文末有公众号二维码)。 -# 类加载过程 +一个类的完整生命周期如下: + + + +![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/类加载过程-完善.png) + +## 类加载过程 Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢? 系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 -![类加载过程](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) +![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) -## 加载 +### 加载 类加载过程的第一步,主要完成下面3件事情: @@ -37,11 +44,11 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 加载阶段和连接阶段的部分内容是交叉进行的,加载阶段尚未结束,连接阶段可能就已经开始了。 -## 验证 +### 验证 ![验证阶段示意图](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/验证阶段.png) -## 准备 +### 准备 **准备阶段是正式为类变量分配内存并设置类变量初始值的阶段**,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意: @@ -52,7 +59,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 ![基本数据类型的零值](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/基本数据类型的零值.png) -## 解析 +### 解析 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。 @@ -60,7 +67,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 综上,解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。 -## 初始化 +### 初始化 初始化是类加载的最后一步,也是真正执行类中定义的 Java 程序代码(字节码),初始化阶段是执行类构造器 ` ()`方法的过程。 @@ -74,6 +81,22 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。 5. 当使用 JDK1.7 的动态动态语言时,如果一个 MethodHandle 实例的最后解析结构为 REF_getStatic、REF_putStatic、REF_invokeStatic、的方法句柄,并且这个句柄没有初始化,则需要先触发器初始化。 +## 卸载 + +> 卸载这部分内容来自 [issue#662](https://github.com/Snailclimb/JavaGuide/issues/662)由 **[guang19](https://github.com/guang19)** 补充完善。 + +卸载类即该类的Class对象被GC。 + +卸载类需要满足3个要求: + +1. 该类的所有的实例对象都已被GC,也就是说堆不存在该类的实例对象。 +2. 该类没有在其他任何地方被引用 +3. 该类的类加载器的实例已被GC + +所以,在JVM生命周期类,由jvm自带的类加载器加载的类是不会被卸载的。但是由我们自定义的类加载器加载的类是可能被卸载的。 + +只要想通一点就好了,jdk自带的BootstrapClassLoader,PlatformClassLoader,AppClassLoader负责加载jdk提供的类,所以它们(类加载器的实例)肯定不会被回收。而我们自定义的类加载器的实例是可以被回收的,所以使用我们自定义加载器加载的类是可以被卸载掉的。 + **参考** - 《深入理解Java虚拟机》