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 启动参数,只在启动时生效:
maven-surefire-plugin 的 <jvmArguments> 配置测试,或 maven-failsafe-plugin 同理;主应用需配合 exec:java 或外部脚本java -jar 命令前加上参数,例如:java --add-opens java.base/java.lang=ALL-UNNAMED -jar app.jar
如果你的项目已声明 module-info.java(比如 module com.example.app),更安全的做法是:
ALL-UNNAMED 换成你自己的模块名:--add-opens java.base/java.lang=com.example.app
com.fasterxml.jackson.databind),也要对应写成该模块名