You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Java 8迁移到Java 17后测试报InaccessibleObjectException,是否因版本变更?

问题分析与解决方案

核心原因

这确实是Java 17(本质是Java 9引入的模块化系统JPMS)的机制变更导致的问题,并非单纯的版本不匹配。

Java 9开始引入模块系统后,JDK核心模块(如java.base)默认会封装内部API和受保护方法,限制外部通过反射访问。java.lang.Object.clone()是java.base模块中java.lang包下的protected native方法,而你的测试代码属于未命名模块(大多数非模块化项目默认如此),java.base模块没有将java.lang包开放给未命名模块,因此当Whitebox.invokeMethod尝试通过反射强行访问该方法时,就会抛出InaccessibleObjectException。Java 17进一步加强了模块化封装限制,这类反射访问的约束比Java 8严格得多。

解决方案

1. 添加JVM参数开放模块访问

最直接的解决方式是在测试运行时添加JVM参数,让java.base模块将java.lang包开放给所有未命名模块。你需要在Maven的maven-surefire-plugin中配置argLine参数:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <!-- 建议升级到适配Java 17的版本,比如3.0.0及以上 -->
            <version>3.2.2</version>
            <configuration>
                <argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

注意:maven-surefire-plugin旧版本对Java 17支持不佳,建议升级到3.0.0以上的稳定版本。

2. 替换Whitebox的反射用法

如果业务允许,尽量避免通过反射访问受保护的JDK核心方法:

  • 如果测试目标类自身重写了clone()方法并公开了访问权限,直接调用该方法即可;
  • 替换为更符合模块化规范的测试工具,比如使用JUnit 5内置的反射工具类,或Mockito的反射API替代Whitebox。

3. 升级测试依赖版本

你的junit-jupiter-engine版本5.8.2发布于2021年,对Java 17的兼容性有限。建议升级到5.9.x及以上版本,能更好地适配Java 17的模块化特性,减少潜在兼容性问题:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.10.1</version>
    <scope>test</scope>
</dependency>

内容的提问来源于stack exchange,提问作者RagaSGNur

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 22:10:35