Java 9模块化系统(JPMS):控制对象变量跨包访问权限指南
作者:SunnyJourney
时间:2026-07-06
浏览:0
JPMS控制跨模块访问权限,不管理同一模块内跨包访问。exports仅开放模块中包的public成员,opens允许反射访问私有成员,包私有类无法被其他模块访问。需注意编译期与运行期差异及反射限制。
今天聊聊 Ja va 9 模块化系统里一个特别容易让人懵圈的问题——它到底控制的是什么东西的访问权限?
先说一个核心判断:JPMS 从来不直接管什么“对象变量”能不能跨包访问。它管的是跨模块的访问权限,具体来说,是一个模块里的包、类、成员,能不能被另一个模块看到、用到。至于同一个模块里不同包之间怎么访问,不好意思,这事依然归传统的 public、protected、包私有、private 这些老伙计管。模块系统只会在模块边界上站岗——当外部模块的代码试图访问你的内部时,它才会出手。
exports:让外部能用,但只给 public
在 module-info.ja va 里写一句 exports com.example.api;,意思很简单:其他模块可以编译和运行时使用这个包里的 public 类及其 public 成员。
- 其他模块能
new这个包里的public类,能调用它的public方法,能读写它的public字段。 - 但如果一个
public class User里,字段name是包私有(没写public),那其他模块依然碰不到它——编译期报错,运行期也过不去。 - 哪怕你用反射
field.setAccessible(true),也会直接抛出IllegalAccessException。因为exports只管“能不能用”,不管“能不能反射”。
简单一句话:exports 只开了一扇门,但门里只有 public 的东西能见光。
opens:给反射开绿灯,连 private 都放行
如果你的类需要被 Spring、Hibernate、JUnit 这类框架通过反射操作非 public 成员,那就必须用 opens 明确授权。
opens com.example.model;→ 所有模块都能通过反射访问这个包里所有类的所有成员,包括private字段和方法。opens com.example.config to spring.core;→ 只对spring.core一个模块开放,安全性高得多。- 需要留意的是:
opens不影响编译期的可见性。换句话说,它不会让其他模块在写代码时就能直接引用包私有的类;它只在运行期给反射开了绿灯。
package-private 类:连模块的门都出不去
如果一个类没有 public 修饰符(也就是包私有),就算你 exports 了整个包,其他模块也根本看不见这个类。这不是反射的问题,是类加载器压根儿不知道有这个类存在。
- 编译时直接报
cannot find symbol - 运行时抛出
NoClassDefFoundError或IllegalAccessError - 模块系统不会“穿透”包级别的封装
- 如果你确实想复用某个实现但又不想暴露为 public API,可以考虑用
provides ... with+ service interface 的模式,把实现类留在包私有里。
常见误判与调试提示
遇到“明明 exports 了却访问不到”这种问题,不要慌,先检查这几个地方:
- 目标类或字段是不是
public?不是的话,exports帮不上忙,得用opens。 - 是否用了
--illegal-access=deny(JDK 16+ 默认设置)?没有opens就直接失败,连警告都不给。 - IDE 可能不报错,因为编译器只校验
exports,真正的拦截发生在 JVM 启动时。建议用jlink或真实模块路径来测试。 - 第三方库(比如 commons-lang3)如果没有
module-info.class,它会变成“自动模块”,exports规则对它不生效。开发环境下可以用--add-opens临时绕过,但生产环境别这么干。

作者最新文章
图几
2026-09-16 17:43
SQL中ROUND函数对0.5的处理机制及强制四舍五入方法
2026-09-15 14:19
JS金额计算怎么避免四舍五入误差
2026-09-14 17:32
韩国8月携号转网数据:Galaxy Z8系列iPhone用户转化率约为Z7系列2倍
2026-09-08 17:02
AE基础教程:如何创建合成并制作关键帧动画
2026-09-04 09:27
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多


































