JVM 类加载机制

星期五, 5月 22, 2026 | 1分钟阅读 | 更新于 星期五, 5月 22, 2026

@

继续学习 jvm 的相关知识,前一个星期都在出差,在现场事情是在太多,没坚持学习,出差回来之后要补上。

我已经学习了jvm的内存结构和垃圾回收机制。

接下来应该学习jvm的类加载机制了。

主要是学习jvm如何使用管理class对象。

java代码编译成字节码运行jvm虚拟机上,.java文件编译成.class文件。

那么.class文件是如何变成jvm里面的class对象的?

class对象初始化

从.class文件变成jvm里面的class对象,步骤如下:

  1. 加载:.class文件的字节流读取进内存,生成class对象
  2. 验证:检查字节码是否有问题
  3. 准备:分配给静态变量内存,并且赋值,值是jvm的默认值,不是代码里面写的初始值。
  4. 解析:将符号引用换成直接引用。
  5. 初始化:执行static代码块,给静态变量赋值初始值。这里是初始值就是代码里面给的初始值。

注意:验证、准备、解析,合起来叫“连接”。

双亲委派模式

jvm的类加载有层次关系,加载类的时候,会先向父加载器派这个加载任务,如果父加载器加载不了,才会由他自己加载。

这样做的目的:

  1. 安全。避免核心类库被篡改,比如我自己写了一个java.land.String,覆盖jdk的String库。因为向上委派,jvm加载的是jdk的String库。
  2. 保证一个类在jvm中唯一,防止重复加载和类型转换异常。

SpringBoot的双亲委派模式

Spring Boot没有打破双亲委派,而是在模型的框架内做扩展。

这样实现了两个功能:

  1. 胖jar
  2. 热重启

胖 Jar = 代码 + 所有依赖的第三方 Jar + 嵌入的 Web 容器 + Spring Boot 启动器,全部打成一个可独立运行的 Jar 包。

胖jar

胖 Jar 的 LaunchedURLClassLoader 它继承 URLClassLoader,父加载器仍是 App ClassLoader。核心改变不是委托顺序,而是类路径的来源:它能从 BOOT-INF/classes/ 和 BOOT-INF/lib/ 下加载类。加载一个类时还是先问父加载器,父加载器找不到这些嵌套路径,自然由它自己从胖 Jar 中加载。本质只是扩展了搜索范围。

热重启

DevTools 的“伪热部署”(快速重启)这是类加载器替换与懒加载理念的漂亮结合。DevTools 使用两个类加载器:

base ClassLoader:加载不变的第三方库。 restart ClassLoader:加载项目中的业务类。

改动代码后,它丢弃旧的 restart ClassLoader 并新建一个,base ClassLoader 保持不动。因为只重新加载项目类,重启速度极快。

初始化时机在这里体现为:只有被用到的业务类才会在 restart ClassLoader 中初始化,完美契合懒加载的高效。

© 2026 My Blog

🌱 Powered by Hugo with theme Dream.