Java17环境运行JUnit测试出现InaccessibleObjectException及空指针异常
问题解决方案
1. 解决Java模块系统反射访问权限异常(InaccessibleObjectException)
这个异常是Java 9之后引入的模块系统默认限制导致的:JDK默认禁止外部代码反射访问JDK内置模块的非公开API,你的报错是业务代码或者依赖的第三方库尝试反射修改java.text.DecimalFormatSymbols的私有方法,而java.base模块没有开放java.text包给未命名模块导致的。
解决方法分为两种:
- 临时兼容方案:给JVM添加启动参数开放对应包的访问权限,JUnit测试场景下直接在运行配置的VM参数里添加即可:
如果后续还出现其他类似的反射权限报错,按照--add-opens java.base/java.text=ALL-UNNAMED--add-opens <模块名>/<包名>=ALL-UNNAMED的格式补加对应参数即可。 - 根本解决:排查是哪个第三方库在反射操作
DecimalFormatSymbols,将该库升级到支持Java 17的版本,目前主流的序列化、工具类库的新版本都已经适配了Java 17的模块系统规则,升级后不需要额外添加启动参数。
2. 解决dwaApplicationService.getDwaApp()返回null的空指针异常
这个空指针大概率和前面的反射权限异常是关联的:反射报错打断了依赖注入、Bean初始化的流程,导致dwaApplicationService没有被正确初始化,或者方法内部逻辑因为反射异常提前中断返回了null。
可以按照下面的步骤排查:
- 先按照上面的方法修复反射权限问题,再重新运行测试,大部分场景下反射异常导致的初始化失败问题解决后,空指针会自动消失。
- 如果修复权限后还是返回null,按下面的方向排查:
- 检查测试类的依赖注入注解是否正确,
@Mock、@InjectMocks、@Autowired等注解有没有漏加;同时确认Mockito版本是否支持Java 17,低于4.x的Mockito版本对Java 17兼容性很差,建议升级到Mockito 4.11及以上版本。 - 检查
getDwaApp()的内部逻辑,有没有因为Java 17的语法变化(比如字符串处理、类型推断规则调整)或者依赖API变更导致返回null的分支被触发。 - 检查测试用的配置文件是否加载正常,高版本JDK对类路径资源加载的规则有细微调整,可能会导致原有配置文件加载失败,进而导致方法返回null。
- 给代码增加防御性判断,避免空指针风险:
@Before public void initApp() throws Exception { app = dwaApplicationService.getDwaApp(); if (app != null) { for (Market m : app.getMarkets()){ // 原有逻辑 } } else { // 按需添加错误日志、抛自定义异常或者mock兜底的DwaApplication对象 } }
- 检查测试类的依赖注入注解是否正确,
内容的提问来源于stack exchange,提问作者Paride Rama
相关产品推荐
相关产品推荐

