确认是opens声明缺失引发的问题,需检查异常是否含InaccessibleObjectException或“does not 'opens'”,定位源模块与目标模块,通过--add-opens参数授权或修正module-info.java中的opens声明。

直接看异常堆栈里有没有 InaccessibleObjectException 或明确提示 “does not ‘opens’” 的语句,基本就能确认是 opens 声明缺失引发的问题。这类异常不是编译失败,而是在运行时反射调用(如 setAccessible(true))触发模块访问检查后被 JVM 拦下的结果。
快速定位报错源头包和模块
异常信息通常包含两段关键路径:
- 前半段指出被访问的类/字段/方法所在包,例如
java.util.ArrayList.elementData→ 源模块是java.base,目标包是java.util - 后半段说明访问方所属模块,例如
to unnamed module @123abc表示你的应用是以传统类路径(CLASSPATH)方式加载的,即未命名模块
用 jdeps --list-deps YourApp.jar 可验证是否含 unnamed module;若项目有 module-info.java,则需查清自己模块名,而非默认用 ALL-UNNAMED。
检查目标模块是否真正开放了对应包
如果报错来自你自己的模块(比如反射访问 com.example.internal.Config),就打开它的 module-info.java:
- 确认该包是否在
exports中——仅导出只允许编译期可见,不解决反射问题 - 必须有
opens com.example.internal;或更精确地opens com.example.internal to spring.core, com.fasterxml.jackson.databind; - 注意:不能写
opens com.example.*;,通配符不被支持
验证 JDK 内部包是否被正确授权
若错误指向 java.base/java.lang、java.base/java.util 等核心包,说明框架(如 Spring、Jackson、Hibernate)正尝试反射访问其私有成员:
- 启动参数必须带上
--add-opens,格式为--add-opens 源模块/包=目标模块 - 对 CLASSPATH 应用,目标模块写
ALL-UNNAMED;对已命名模块,应写具体模块名,例如--add-opens java.base/java.lang=com.example.app - 多个包要放开,需重复写多条,不能合并成一条
避免误判为其他类型错误
有些现象容易混淆,需主动排除:
-
IllegalAccessError和IllegalAccessException不同:前者是 JVM 解析符号引用时失败,后者是反射 API 主动抛出的受检异常 - 堆栈中没出现
Module、jdk.internal.module或not open to module字样,大概率不是模块问题,而是普通访问权限或类加载隔离导致 - 加了
--add-opens还报错?检查参数是否传给了正确的 JVM 进程(如mvn test和mvn spring-boot:run需分别配置)

















