bigywater.tech
Java · 200

Module Layer:运行时如何创建隔离模块层

模块层(ModuleLayer)让运行时可以创建彼此隔离的模块集合。这篇用同一个模块的两个版本做实验,验证隔离、exports 与服务查找(模块系统的静态部分见前面 Java 模块系统一篇,URLClassLoader 插件见上一篇)。

62 个
启动层里的模块数(greeter 不在其中)
v1 与 v2 同时存在
两个层里的 greeter 模块各有自己的 Greeter 类
IllegalAccessException
反射访问层内模块未导出的包

启动层与新层

实测 · 本机执行输出
  启动层(boot layer)的模块数 = 62,父层 = [];greeter 在启动层里吗:false
  Main 所在的模块:unnamed module @85ede7b,isNamed = false,getLayer() = null(类路径上的代码在未命名模块里,不属于任何层)
  新建层(从 mods1 目录解析 greeter v1):模块 = [greeter],父层 = [boot],层里的模块的类加载器 = jdk.internal.loader.Loader,与应用类加载器相同吗:false
  Module.getLayer() == 新层:true;boot.findModule("greeter") 仍然是 false

两个版本

实测 · 本机执行输出
  层里的 greeter:Greeter.version() = 1,greet("ann") = v1 greets ann,类加载器 = Loader@12e…
  层里的 greeter:Greeter.version() = 2,greet("ann") = v2 greets ann,类加载器 = Loader@476…
  两个层里的 greet.Greeter 是同一个类吗:false;两个版本同时在一个 JVM 里运行

exports 与服务

实测 · 本机执行输出
  Class.forName(module, "internal.Util") 能找到类:true
  反射调用未导出包 internal 里的 Util.tag() → IllegalAccessException: class Main cannot access class internal.Util (in module greeter) because module greeter does not export internal to unnamed module @254989ff
  greeter 是否导出了 greet 包给所有模块:true;是否导出 internal:false
  ServiceLoader.load(layer, Service) 找到的实现:greet.Impl → hello from greeter v1, internal says util-v1

重复创建与失败

实测 · 本机执行输出
  同一份模块再创建一个层:两个层里的 greeter 模块是同一个 Module 对象吗:false
  解析一个不存在的模块 → FindException: Module nosuchmodule not found

分步演示

ModuleLayer
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12
    • 没有验证:defineModulesWithManyLoaders 与 OneLoader 在多模块层里的差别(本篇的层里只有一个模块)、层的卸载(GC)、自动模块与 requires transitive 的解析、层与 Spring/OSGi 等框架的对比;启动层的模块数随命令行 --add-modules 变化
    京ICP备2026067502号-1京公网安备11010502063487号