当前位置: 首页 > news >正文

从 rt.jar 到模块化:JDK9 类加载机制的全面演进

前言

从 JDK 9 开始,Java 引入了革命性的 模块系统(Java Platform Module System,JPMS)。它让整个 JDK 实现了彻底的模块化,也使类加载机制发生了根本变化。

新的目标是:

  • 让 JDK 本身模块化(如 java.base、java.sql 等);
  • 摆脱庞大的 rt.jar;
  • 提升性能、封装性与可维护性。

为了理解这种变化,我们先从 JDK 8 的类加载机制讲起。

一、JDK8启动类加载器

概念

启动类加载器是最顶层的类加载器

  • 是 由 C/C++ 实现的本地代码(Native Code)
  • 不是真正意义上的 Java 对象(在 Java 层你拿不到它的实例);
  • 主要负责加载 JRE 核心类库

加载哪些内容

加载来源:$JAVA_HOME/jre/lib/rt.jar 和少量附属 JAR。

加载的典型包有:

类或包说明
java.lang.*核心语言类(String、Object、Thread、Class 等)
java.io.*IO 基础类
java.net.*网络类
java.util.*集合、工具类
java.math.*BigDecimal、BigInteger
java.text.*文本处理
java.security.*安全相关类
javax.crypto.*加密
sun.*许多内部类(如 sun.misc.Unsafe
...基本所有标准核心 API

这些都被打包在 rt.jar 和其他系统 jar(resources.jarjsse.jarcharsets.jar)中。

可用命令查看:

java -XshowSettings:properties -version | grep boot.class.path

特点

特点问题
所有核心类集中在 rt.jar文件巨大(60MB+),启动慢
统一加载所有核心类无法按需加载或裁剪
依赖关系隐式存在没有模块边界,依赖模糊
类加载路径通过 boot.class.path 配置不支持模块化描述

二、JDK9的启动类加载器

JDK 9 的模块系统彻底重构了类加载架构。

不再使用 rt.jar,而是引入了新的 模块化加载体系,让每个模块自成单元、依赖明确。

JRT文件系统镜像

在 JDK 9 之前,所有核心类放在:

$JAVA_HOME/jre/lib/rt.jar

而在 JDK 9 之后,这些类被打包成一个 特殊的二进制镜像文件

$JAVA_HOME/lib/modules

这个文件是一个 JRT(Java Runtime Image)文件系统镜像

“JRT” 代表 “Java RunTime”
它不是 zip/jar,而是专门为 Java 设计的高效只读文件系统格式。

modules 文件中包含所有模块的 .class 文件:

可以用命令查看内容:

$JAVA_HOME/bin/jimage list $JAVA_HOME/lib/modules | head
(base) mumu@MacBook-Pro-21 ~ % $JAVA_HOME/bin/jimage list $JAVA_HOME/lib/modules | head
jimage: /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/lib/modulesModule: java.basejava/io/Bits.classjava/io/BufferedInputStream.classjava/io/BufferedOutputStream.classjava/io/BufferedReader$1.classjava/io/BufferedReader.classjava/io/BufferedWriter.classjava/io/ByteArrayInputStream.classjava/io/ByteArrayOutputStream.classjava/io/CharArrayReader.classjava/io/CharArrayWriter.classjava/io/CharConversionException.classjava/io/ClassCache$1.classjava/io/ClassCache$CacheRef.classjava/io/ClassCache.classjava/io/Closeable.class......
  • 每个模块对应一个“虚拟目录”(如 java.base/java.sql/
  • 每个目录里有模块内的 class 文件。

每个模块都有一个描述文件:系统在启动时,会根据这些描述文件建立 模块依赖关系图(Module Graph)

// module-info.java
module java.sql {requires java.base;exports java.sql;
}

JVM如何读取这些文件

JVM 在启动时会挂载一个虚拟文件系统:

jrt:/

你可以像访问文件系统一样访问模块中的类。

示例:

jrt:/java.base/java/lang/String.class

Java 9+ 提供了一个标准 API 来访问它:

FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); 
Path path = fs.getPath("modules", "java.base", "java/lang/String.class"); 
System.out.println(Files.exists(path)); // true

为什么要用 JRT 镜像而不是 jar?

对比项rt.jarmodules(JRT 镜像)
格式ZIP专用镜像格式
加载方式传统类路径扫描模块索引快速定位
扩展性不支持模块依赖支持模块化描述
启动性能慢,需要解压索引快,直接映射内存
定制能力无法拆分支持 jlink 打包精简 JRE

JRT 镜像让 JVM 启动更快、内存占用更低,同时为模块化打下基础。

BuiltinClassLoader 与模块加载的关系

🧩 类加载器体系变化

JDK9 对类加载体系进行了重构:

类加载器JDK 8 实现JDK 9+ 实现
启动类加载器(Bootstrap)C/C++ 实现BuiltinClassLoader 子类
扩展类加载器(Ext)Launcher$ExtClassLoader平台类加载器(PlatformClassLoader)
应用类加载器(App)Launcher$AppClassLoaderBuiltinClassLoader 子类

🧩 BuiltinClassLoader 是什么?

BuiltinClassLoader 是 JDK9 新增的统一类加载器基类

它负责:

  • 从模块系统中查找类;
  • 支持模块依赖与索引;
  • 提供统一缓存与并发加载;
  • 替代原先的 ExtClassLoader / AppClassLoader
package jdk.internal.loader;
public class BuiltinClassLoader extends SecureClassLoader { ... }

BuiltinClassLoader 如何从模块中加载类?

简化伪代码示例:

protected Class<?> findClass(String name) throws ClassNotFoundException {// 1. 通过模块系统查找模块Module module = moduleFinder.findModuleForClass(name);// 2. 通过 JRT 文件系统解析路径Path classFile = JRTFileSystem.resolve(module, name);// 3. 读取字节码并定义类byte[] bytes = Files.readAllBytes(classFile);return defineClass(name, bytes, 0, bytes.length);
}

JDK 内部通过 ClassPathImageReader 从 .jmod 或 .jimage 文件中直接读取字节码,
不再像之前那样扫描文件夹或解压 jar。

这大大提升了性能和加载安全性。

三、总结对比

项目JDK 8JDK 9+
核心类来源rt.jar模块镜像 $JAVA_HOME/lib/modules
类加载实现全由 native BootstrapClassLoader 完成BuiltinClassLoader 模块化实现
类加载路径sun.boot.class.path模块层(Module Layer)
加载层级Bootstrap → Ext → AppBootstrap → Platform → App
模块化支持JPMS 模块系统
可裁剪性支持 jlink 精简定制运行时
性能启动慢、内存大模块索引快速加载
核心加载类sun.misc.Launcher$ExtClassLoaderjdk.internal.loader.BuiltinClassLoader
http://www.dtcms.com/a/524553.html

相关文章:

  • 列举一些数据仓库面向主题的设计的实际案例
  • 网站托管服务适合wordpress上传视频黑屏
  • MongoDB 8.x 制作一键部署安装包文档分享(Linux / Windows )
  • Data Warehouse简介
  • 若依 - idea集成docker一键部署springboot项目(docker-compose)
  • 2025 年 MathorCup 大数据建模竞赛 AB 题:高质量全方案・成品资料速取(含双代码 + 论文)
  • 为什么 idea 建议去掉 StringBuilder,使用“+”拼接字符串
  • 2025年数字人语音合成师专业能力测试
  • 门户网站建设思维导图wordpress表格显示图片
  • 【案例实战】基于 AGC 云开发与元服务构建智能待办应用
  • 【第五章:计算机视觉-项目实战之推荐/广告系统】2.粗排算法-(3)理解粗排模型之在线部分:在线架构及对双塔的应用
  • Spring Boot 起步:自动装配的魔法
  • 嵌入式软件架构--显示界面2(呼叫界面,密码界面)
  • 购物网站制作怎么做wordpress移动自媒体
  • 酒店网站做的比较好的钓鱼网站的制作教程
  • 从理论到实战:生成对抗网络(GAN)在图像生成中的关键技巧与完整代码剖析
  • 在K8S中部署MySQL主从
  • go strconv包介绍
  • 论文阅读12——基于学习的具有扩散行为的人流量预测方法
  • 对于随机变量x1, …, xn,其和的范数平方的期望不超过n倍各随机变量范数平方的期望之和
  • ARM《3》_学习c和汇编的混合编程
  • 硬件工程师11月实战项目-10G高速数字示波器开发
  • FPGA Debug:Vivado程序综合卡在了Run Synthesis
  • 免费网站建设推广服务什么样的公司愿意做网站
  • 世隆科技:无人船——开启水上智能作业新时代
  • 网站后台模板关联自己做的网站电商网站楼层 设计
  • 【北京迅为】iTOP-4412精英版使用手册-第六十八章 U-boot基础知识
  • 关于函数调用其实是函数指针+传参+解引用的一些思考
  • 奇缦科技珠海网站建设优化网站地图样本
  • 【设计模式】组合模式(Composite)