如何调试Java运行时带哈希命名的未命名模块报错问题
Java 模块化跨模块访问报错标准调试方法
首先先拆解这类报错的固定结构,你给出的报错核心信息可分为3个明确要素:
java.lang.IllegalAccessError: superclass access check failed: class com.oracle.truffle.polyglot.PolyglotImpl (in unnamed module @0x58a90037) cannot access class org.graalvm.polyglot.impl.AbstractPolyglotImpl (in module org.graalvm.sdk) because module org.graalvm.sdk does not export org.graalvm.polyglot.impl to unnamed module @0x58a90037
- 访问方:
com.oracle.truffle.polyglot.PolyglotImpl,归属 未命名模块(unnamed module @0x58a90037) - 被访问资源:
org.graalvm.polyglot.impl.AbstractPolyglotImpl,归属已命名模块org.graalvm.sdk - 拦截原因:
org.graalvm.sdk未将org.graalvm.polyglot.impl包导出给访问方所在的模块
标准调试步骤
- 第一步:定位访问方所属依赖
不要盲目添加requires声明,先通过全类名搜索报错中的访问方(本案例为com.oracle.truffle.polyglot.PolyglotImpl)属于哪个Jar包,再查询该Jar对应的官方模块名。本案例中该类归属org.graalvm.js模块,直接添加该模块的requires即可,该模块官方已经声明了所需的org.graalvm.sdk对应包的访问权限,无需自行声明sdk依赖。 - 第二步:按访问方模块类型处理
- 如果访问方为未命名模块:说明对应Jar放在类路径下未被模块化体系识别,可二选一处理:
- 引入该Jar的官方模块化版本,或为其手动添加模块化声明
- 调试阶段可临时加启动参数开放权限:
--add-exports <被访问模块名>/<被访问包名>=ALL-UNNAMED,不建议线上环境使用
- 如果访问方为已命名模块:检查访问方模块是否声明了对应资源的
requires,或被访问模块是否将对应包导出给访问方,可通过启动参数定向开放:--add-exports <被访问模块名>/<被访问包名>=<访问方模块名>
- 如果访问方为未命名模块:说明对应Jar放在类路径下未被模块化体系识别,可二选一处理:
- 第三步:验证依赖传递关系
配置完成后用构建工具查询依赖树:Maven执行mvn dependency:tree,Gradle执行gradle dependencies,确认添加的模块已正确引入,无版本冲突。多数requires声明无效的问题都是模块版本不兼容导致。 - 第四步:Spring生态适配规则
Spring生态对Java模块化有约定好的适配规则,无需全量开放模块:- 自定义模块需要被Spring扫描时,仅需给对应业务包添加声明:
opens <你的业务包名> to spring.core, spring.beans, spring.context - 用到Spring Boot自动配置时,添加声明:
opens <你的配置类包名> to spring.boot.autoconfigure
- 自定义模块需要被Spring扫描时,仅需给对应业务包添加声明:
本案例问题根因
你之前添加requires org.graalvm.sdk;无效,是因为sdk模块的org.graalvm.polyglot.impl属于内部包,默认仅导出给官方配套的实现模块(比如org.graalvm.js),不会开放给外部自定义模块。添加requires org.graalvm.js后,该模块自带的内部权限声明会自动生效,因此报错消失。
内容的提问来源于stack exchange,提问作者Salathiel Genese
相关产品推荐
相关产品推荐

