不能通过module-info.java实现变量强隔离;它仅声明模块名、导出包、依赖关系、反射开放及服务契约,不控制类加载或静态变量作用域,变量隔离必须依赖独立ClassLoader实现类型物理隔离。
不能通过
实现变量强隔离。
module-info 的作用边界很明确
是 Java 9 引入的模块系统(JPMS)声明文件,它只负责:
声明模块名、导出(
)哪些包给其他模块使用
要求(
)哪些模块、是否可选或静态依赖
打开(
)包用于反射、服务加载等特殊场景
声明服务提供(
)与使用(
)
它
不控制类加载行为
,也不影响类的实例化、静态字段生命周期或内存布局。即使两个模块都导出同名类
,只要它们被同一个
加载(比如默认的
),JVM 就只认作一个类——其
在整个 JVM 中仍是共享的。
变量隔离的本质是类加载隔离
真正让变量(尤其是静态变量)互不干扰的关键,在于让同名类由
不同的 ClassLoader 实例
加载。此时:
JVM 将它们视为完全无关的类型,哪怕字节码一模一样
各自拥有独立的方法区(Metaspace)数据,包括静态字段存储空间
模块 A 中的
不会影响模块 B 中的
这和
是否存在、是否
该类毫无关系。JPMS 模块系统本身仍运行在传统双亲委派模型之上,无法打破类加载器层级带来的类型唯一性约束。
可行的强隔离路径:绕过 JPMS,用 ClassLoader 分层
若你确实需要模块间变量强隔离(如插件系统、多租户配置类、动态脚本上下文),应放弃依赖
,转而构建显式的类加载隔离层:
为每个业务模块创建独立的
,且设置
或自定义父加载器,彻底切断双亲委派
确保各模块 JAR 的 classpath 严格分离,避免交叉可见
通过接口契约通信(如定义在公共父类加载器中的 SPI 接口),禁止直接传递模块私有类的实例
配合资源隔离(如独立配置目录、线程上下文绑定)进一步强化边界
Spring 的
、脚本引擎的
、OSGi 的 Bundle ClassLoader,都是这一思路的成熟实践。
JPMS 与 ClassLoader 隔离不是替代关系,而是不同层级
JPMS 解决的是
编译期与链接期的可见性、封装性与依赖声明问题
;ClassLoader 隔离解决的是
运行时类型的物理分隔与状态独立问题
。二者可共存——例如用 JPMS 管理模块依赖拓扑,再用自定义 ClassLoader 加载每个模块的实现类。但切记:
本身不提供变量隔离能力,也不能替代类加载器的职责。
module-info.javamodule-info.javaexportsrequiresopensprovidesusescom.example.ConfigClassLoaderAppClassLoaderstatic int version = 1Config.counter++Config.countermodule-infoexportsmodule-infoURLClassLoaderparent = nullServiceClassLoaderGroovyClassLoadermodule-info