Java Platform Module System,JPMS,JDK 9 引入的 Java 模块化系统,可配置的封装隔离机制;

  • 通过模块间的显示依赖,支持 JVM 在启动时验证应用程序的运行期依赖是否完备,可以避免在运行期间因类加载、连接失败而抛异常;
  • 模块提供了更精细的可访问性控制(可以声明哪些 public 类可被其他哪些模块访问),不再意味着程序的所有地方都能访问 public 类型;

模块化定义

  • 依赖其他模块的列表;
  • 导出的包列表,即可被其他模块引用的列表;
  • 开放的包列表,即其他模块通过反射可访问的模块列表;
  • 使用的服务列表;
  • 提供服务的实现列表;


文章目录

  • 1. 模块的兼容性
  • 2. 模块化下的类加载器


1. 模块的兼容性

JDK 9 引入了与类路径(ClassPath)相对应的模块路径(ModulePath)的概念,用于兼容传统类路径查找机制;

  • 只要是放在类路径上的 JAR 文件,即使包含模块化信息,包含了 module-info.class 文件,也会被当作传统的 JAR 包来对待;
  • 只要是放在模块路径上的 JAR 文件,即使没有使用 JMOD 后缀,即使不包含 module-info.class 文件,它也会被当作一个模块来对待;

访问规则

  • 匿名模块Unnamed Module),即传统类路径上的所有传统 JAR 文件;它可以看到和使用类路径上所有的包、JDK 系统模块中所有导出的包、模块路径上所有模块导出的包;
  • 具名模块Named Module),即模块路径上的模块;只能访问它明确依赖的模块和包,匿名模块的所有内容(传统 JAR 包的内容)对具名模块不可见;
  • 自动模块Automatic Module),即模块路径上不包含模块定义的传统 JAR 文件; 虽然不包含 module-info.class,但它默认导出自己所有的包,并可以访问所有模块导出的包;

不经任何修改的传统类依赖版 Java 程序在 JDK 9 以上版本运行几乎不会受到模块化影响;

JPMS 目前不支持在模块定义中管理和约束版本号,不支持版本号概念和版本选择功能;

JPMS 不支持运行时热替换、模块热部署能力,仍需通过类加载器去实现;JVMTI 接口(java.lang.instrument.Instrumentation)也只提供了运行时修改类的能力(RedefineClass、RetransformClass),不能添加新成员、删除已有成员、修改已有成员的签名等;

2. 模块化下的类加载器

扩展类加载器Extension Class Loader)被平台类加载器Platform Class Loader)取代;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LzT9eOpy-1675990882394)(./images/ClassLoader-Module.png)]

平台类加载器,以及原有的启动类加载器、应用类加载器都不再继承自 java.net.URLClassLoader,而是继承自 jdk.internal.loader.BuiltinClassLoader,该类实现了新的模块化架构下的类如何从模块中加载、模块资源可访问性控制等功能;

JPMS 下的委派关系

当平台类加载器和应用程序类加载器收到类加载请求,会先判断该类是否能归属到某个系统模块中,若找到其归属关系,就优先委派给负责这个模块的加载器进行加载,否则才会委派给父类加载器;

  • 启动类加载器负责的模块
java.base                           java.security.sasl
java.datatransfer                   java.xml
java.desktop                        jdk.httpserver
java.instrument                     jdk.internal.vm.ci
java.logging                        jdk.management
java.management                     jdk.management.agent
java.management.rmi                 jdk.naming.rmi
java.naming                         jdk.net
java.prefs                          jdk.sctp
java.rmi                            jdk.unsupported
  • 平台类加载器负责的模块
java.activation*                    jdk.accessibility
java.compiler*                      jdk.charsets
java.corba*                         jdk.crypto.cryptoki
java.scripting                      jdk.crypto.ec
java.se                             jdk.dynalink
java.se.ee                          jdk.incubator.httpclient
java.security.jgss                  jdk.internal.vm.compiler*
java.smartcardio                    jdk.jsobject
java.sql                            jdk.localedata
java.sql.rowset                     jdk.naming.dns
java.transaction*                   jdk.scripting.nashorn
java.xml.bind*                      jdk.security.auth
java.xml.crypto                     jdk.security.jgss
java.xml.ws*                        jdk.xml.dom
java.xml.ws.annotation*             jdk.zipfs
  • 应用程序类加载器负责的模块
jdk.aot                             jdk.jdeps
jdk.attach                          jdk.jdi
jdk.compiler                        jdk.jdwp.agent
jdk.editpad                         jdk.jlink
jdk.hotspot.agent                   jdk.jshell
jdk.internal.ed                     jdk.jstatd
jdk.internal.jvmstat                jdk.pack
jdk.internal.le                     jdk.policytool
jdk.internal.opt                    jdk.rmic
jdk.jartool                         jdk.scripting.nashorn.shell
jdk.javadoc                         jdk.xml.bind*
jdk.jcmd                            jdk.xml.ws*
jdk.jconsole

上一篇:「JVM 执行子系统」类加载器与双亲委派模型 下一篇:「JVM 执行引擎」 虚拟机栈的栈帧结构

PS:感谢每一位志同道合者的阅读,欢迎关注、评论、赞!


参考资料:

  • [1]《深入理解 Java 虚拟机》