Java高级——模块化系统

模块化系统

  • 简述
  • 模块的兼容性
  • 模块化下的类加载器

简述

JDK 9中引入的Java模块化系统(Java Platform Module System,JPMS),实现了可配置的封装隔离机制,相较于之前只包含代码的JAR包,其还包括:

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

JDK 9之前基于类路径(ClassPath)来查找依赖,若缺失,则等程序运行到该类型的加载、链接时才会报出运行时异常

在JDK 9以后,若启用了模块化封装,模块可声明对其他模块的显式依赖,JVM在启动时验证依赖关系,若缺失则启动失败,从而避免部分由于依赖而引发的运行时异常

模块提供了更精细的可访问性控制,必须明确声明其中哪一些public的类型可以被其他哪一些模块访问

模块的兼容性

为了使可配置的封装隔离机制能够兼容传统的类路径查找机制

  • 类库是模块还是JAR包取决于存放的路径
  • 类路径下的JAR,无论是否包含模块化信息(module-info.class文件),都当作JAR包
  • 模块路径下的JAR,即使没JMOD后缀,甚至不包含module-info.class文件,仍当作模块

为了保证使用传统类路径依赖的Java程序可以不经修改地直接运行在JDK 9及以后的版本,制定以下规则

  • JAR在类路径:打包为匿名模块(Unnamed Module),没有任何隔离,它可以看到和使用类路径、JDK系统模块和模块路径中所有的导出包
  • 模块在模块路径:具名模块(Named Module)只能访问其依赖定义中列明依赖的模块和包,无法访问匿名模块
  • JAR在模块路径:打包为自动模块(Automatic Module),默认导出自己所有的包,依赖模块路径中的所有模块,因此可以访问到所有模块导出的包

JPMS因为商业原因目前不支持在模块定义中加入版本号来管理和约束依赖,本身也不支持多版本号的概念和版本选择功能

若同一个模块发行了多个不同的版本,只能在编译打包时通过javac–module-version选择模块版本来保证依赖的正确性

所以也不支持多版本模块并存、运行时热替换、热部署模块的能力,仍须通过类加载器去实现(将OSGi和JPMS混合使用)

模块化下的类加载器

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

  • JDK基于模块化构建,本身满足了可扩展性,无需使用\lib\ext或java.ext.dirs扩展
  • 取消了\jre,可利用模块构建出程序运行所需的JRE

平台类加载器和应用程序类加载器都不再派生自java.net.URLClassLoader

Java高级——模块化系统_第1张图片
新增启动类加载器(但获取仍返回null),与平台类加载器、应用程序类加载器一同继承于jdk.internal.loader.BuiltinClassLoader,其实现了模块化架构下类加载逻辑,以及模块中资源可访问性的处理

Java高级——模块化系统_第2张图片

当平台或应用程序类加载器收到类加载请求,在委派给父加载器前先判断该类能否归属到某模块中,若能则先委派给该模块的加载器完成加载

启动类加载器负责加载的模块:

Java高级——模块化系统_第3张图片
平台类加载器负责加载的模块:

Java高级——模块化系统_第4张图片

应用程序类加载器负责加载的模块:

Java高级——模块化系统_第5张图片

你可能感兴趣的:(#,Java高级,java,jvm,开发语言)