
Unable to make field private final java.lang.String java.io.File.path accessible: module java.base 问题猫头虎 在使用 Java 9 及以上版本时,模块化(Module System)带来的反射限制常会导致如下异常:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not “opens java.io” to unnamed module @...本教程将结合 JDK 8、JDK 11、JDK 17、JDK 21 环境,分步详解该问题的成因及解决方法,帮助你快速上手处理模块化反射访问失败的场景。
java.io.File 的私有字段(如 path)时,会因未打开相应包而抛出 InaccessibleObjectException。JDK 版本 | 模块化支持 | 是否抛出异常 |
|---|---|---|
JDK 8 | 否 | 不会抛出 |
JDK 11 | 是 | 会抛出 InaccessibleObjectException |
JDK 17 | 是 | 同 JDK 11 |
JDK 21 | 是 | 同 JDK 11 |
java.base/java.io 包至调用代码所在模块/unnamed module。
module-info.java 声明。对于 JDK ≥ 9,推荐使用 JVM 参数 方式,命令行启动时添加:
# 打开 java.base 模块中的 java.io 包给所有 unnamed module
java --add-opens java.base/java.io=ALL-UNNAMED -jar your-app.jar打开 Run/Debug Configurations。
在 VM options 中加入:
--add-opens=java.base/java.io=ALL-UNNAMED保存并运行。
在 pom.xml 的 <plugin> 配置里,针对 maven-surefire-plugin 和 maven-compiler-plugin 添加:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>--add-opens java.base/java.io=ALL-UNNAMED</argLine>
</configuration>
</plugin>tasks.withType(Test) {
jvmArgs += "--add-opens=java.base/java.io=ALL-UNNAMED"
}如果你的项目本身采用模块化(即存在 module-info.java),可以在项目模块的声明中添加:
// module-info.java
module your.module.name {
// 允许本模块使用反射访问 java.io 包
opens java.io to your.module.name;
// 其他依赖声明
requires java.base;
}⚠️ 注意
opens 只能对自定义模块生效,对 java.base 这样的 JDK 模块,仍需 JVM 参数 --add-opens。opens 形式适用于拆分自身项目模块内各包的进出权限管理,不是针对 JDK 模块的开放。以下示例演示了无额外参数和加了 --add-opens 参数时的运行结果对比。
import java.lang.reflect.Field;
import java.io.File;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Field pathField = File.class.getDeclaredField("path");
pathField.setAccessible(true); // 这里会触发 InaccessibleObjectException
File f = new File("test.txt");
System.out.println(pathField.get(f));
}
}不带参数运行(JDK 11+)
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module @...带参数运行
java --add-opens java.base/java.io=ALL-UNNAMED ReflectTest
# 输出 "test.txt"--illegal-access=permit?
A:该参数只在 JDK 9~15 默认允许非法访问,JDK 16+ 已移除,不建议依赖。module java.base does not “opens java.lang”,同理添加 --add-opens java.base/java.lang=ALL-UNNAMED。--add-opens java.base/java.io=ALL-UNNAMEDmodule-info.java 中使用 opens(仅限自定义模块)。
通过本教程,你已掌握了在不同 JDK 版本下,快速定位并修复 “Unable to make field … accessible” 异常的实战方法。祝你编码顺利,项目无忧!
✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️✍️