最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java中 Java 9+ 模块化 JPMS 下反射访问私有成员抛出 InaccessibleObjectException 怎么配置 add-opens
时间:2026-07-26 17:53:04 编辑:袖梨 来源:一聚教程网
Java 9+ 中 setAccessible(true) 因 JPMS 模块封装限制抛 InaccessibleObjectException,需用 --add-opens java.base/java.lang=ALL-UNNAMED 等 JVM 参数显式授权,格式严格、大小写敏感、运行时生效。
Java 9+ 引入 JPMS 后,setAccessible(true) 不再能绕过模块封装限制,反射访问私有成员(字段、方法、注解等)会直接抛 InaccessibleObjectException。这不是代码写错了,而是 JVM 在模块边界上主动拦截——必须通过 --add-opens 显式授权才能通行。
看异常信息,精准定位要开放的模块和包
异常堆栈里一定包含关键线索,例如:
Unable to make field private final java.lang.String java.lang.String.value accessible: module java.base does not "opens java.lang" to unnamed module从中提取三要素:
-
源模块名:
java.base(异常中 “module java.base”) -
目标包名:
java.lang(引号中 “opens java.lang”) -
调用方身份:
unnamed module(即类路径启动的应用,默认叫 unnamed module)
对应参数就是:--add-opens java.base/java.lang=ALL-UNNAMED
立即学习“Java免费学习笔记(深入)”;
正确写法:格式不能错,粒度不能粗
--add-opens 必须严格按 源模块/包=目标模块 格式书写,常见错误包括:
- 漏写包名(如
--add-opens java.base=ALL-UNNAMED→ 无效) - 写错包路径(如
java.lang.String是类,真正要开的是java.lang包) - 误用通配符或合并写法(如
--add-opens java.base/*=ALL-UNNAMED或多包合并在一条里 → 不支持) - 把
ALL-UNNAMED写成all-unnamed(大小写敏感,必须全大写)
多个包需要开放?逐条写:
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/jdk.internal.misc=ALL-UNNAMED运行时加,不是编译时加
--add-opens 是 JVM 启动参数,只在启动时生效:
- IDE 中(如 IntelliJ):在 Run/Debug Configurations → VM options 里填写,不要放在 Program arguments 或其他位置
-
Maven:用
maven-surefire-plugin的<jvmArguments>配置测试,或maven-failsafe-plugin同理;主应用需配合exec:java或外部脚本 -
打包后运行:在
java -jar命令前加上参数,例如:java --add-opens java.base/java.lang=ALL-UNNAMED -jar app.jar
如果用了命名模块,建议用模块名代替 ALL-UNNAMED
如果你的项目已声明 module-info.java(比如 module com.example.app),更安全的做法是:
- 把
ALL-UNNAMED换成你自己的模块名:--add-opens java.base/java.lang=com.example.app - 这样避免意外影响其他 unnamed 模块,也符合模块系统的设计意图
- 若反射调用方是第三方库模块(如
com.fasterxml.jackson.databind),也要对应写成该模块名