modulelayer是jpms提供的可编程模块分层模型,替代扁平classpath,为插件提供独立模块图、专属classloader及显式读取边界,实现多版本依赖隔离。

Java 模块化系统(JPMS)中的 ModuleLayer 并不是对传统类加载器层级的“修补”,而是用一套新的、可编程的、层次化的模块加载模型,替换了过去扁平、隐式、全局共享的类路径(classpath)加载逻辑。它不冲击旧机制,而是提供了一种更可控、更隔离的替代路径——尤其在插件、多版本依赖、动态扩展等场景中,传统双亲委派模型已力不从心。
传统类加载:扁平信任 + 隐式共享
在 Java 8 及之前,所有 JAR 都被加载到同一个 运行时类空间 中,由启动类加载器、扩展类加载器、应用类加载器构成固定三层结构,遵循双亲委派。但关键问题是:
- 一旦某个类被任意类加载器加载,它就对整个应用可见(只要访问权限允许)
- 没有机制阻止两个不同版本的 Jackson 被同时加载——JVM 不识别“版本”,只认全限定类名
- 无法为插件 A 和插件 B 分别准备互不干扰的依赖环境
ModuleLayer:显式分层 + 独立模块图
JPMS 引入 ModuleLayer 后,每个层都拥有自己的:
- 独立的模块图(module graph),包含该层内所有模块及其
requires关系 - 专属的
ClassLoader实例(通常为LayerClassLoader),只负责加载本层模块的类 - 明确的读取权限(readability)边界:一个层里的模块默认 不可见 另一层的模块,除非显式建立 layer-to-layer 的 reads 关系
例如,主机应用运行在 boot layer(含 JDK 模块)和 app layer(主业务模块)上;当加载插件 A 时,可创建新 ModuleLayer,其内部包含 jackson-databind 2.14 和插件 A 自身模块;插件 B 则另起一层,使用 jackson-databind 2.10 ——二者类空间完全隔离,com.fasterxml.jackson.databind.ObjectMapper 在各自层里是不同类,不会冲突。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
Layer 与 ClassLoader 的关系:解耦但协作
ModuleLayer 不是类加载器,但它持有并管理一个专用类加载器:
- 每个
ModuleLayer实例关联一个ClassLoader,该加载器仅委托给父层(parent layer)的类加载器,而非传统意义上的“双亲” - 模块内的类只能通过本层的
ClassLoader加载,且仅能访问本层导出(exports)+ 父层可读(reads)的包 - 这意味着:即使两个层都加载了同名类(如
org.slf4j.Logger),它们在 JVM 中属于不同Class对象,不能互相赋值或强制转换
实际影响:从“类路径战争”走向“模块边界治理”
开发者不再需要靠 URLClassLoader 手动隔离或用 Maven shade 插件重命名包。而是通过编程方式构建 layer:
- 调用
Configuration.resolveAndBind()构建模块配置 - 用
ModuleLayer.boot().defineModulesWithOneLoader()或自定义ClassLoader创建新层 - 通过
layer.modules()获取模块集合,再用Module::getLayer()反查归属
这种能力让 JExten、Renew 4.0 等插件化系统得以在单 JVM 进程中安全共存多个不兼容版本的依赖,而无需 fork 进程或容器隔离。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










