一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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),也要对应写成该模块名

热门栏目