JDK9以上的非法反射访问警告解决方法

目录
文章目录隐藏
  1. 1. 问题描述
  2. 2. 原因
  3. 3. –illegal-access
  4. 4. 总结

1. 问题描述

JDK9以上很多库都有这种非法反射访问的警告,比如protostuff

非法反射访问的警告

解决方法两个:

  • JDK降级
  • 添加 JVM参数

2. 原因

降到JDK8能解决以上问题。

但是这不是本文的重点。

先说一下出现该警告的原因,笔者使用的 JDK 为 OpenJDK 11,JDK9 以上模块不能使用反射去访问非公有的成员/成员方法以及构造方法,除非模块标识为 opens 去允许反射访问。旧 JDK 制作的库(JDK8 及以下)运行在 JDK9 上会自动被标识为未命名模块,为了处理该警告,JDK9 以上提出了一个新的 JVM 参数:--illegal-access

3. –illegal-access

该参数有四个可选值:

  • permit:默认值,允许通过反射访问,因此会提示像上面一样的警告,这个是首次非法访问警告,后续不警告;
  • warn:每次非法访问都会警告;
  • debug:在warn的基础上加入了类似e.printStackTrace()的功能;
  • deny:禁止所有的非法访问除了使用特别的命令行参数排除的模块,比如使用--add-opens排除某些模块使其能够通过非法反射访问。

因此解决的办法很简单,将其设置为deny,并添加--add-opens开启对应的允许非法反射访问的模块即可。

可以通过先设置为debug找到对应的非法访问的代码,比如protostuff中的非法反射访问代码段如下:

protostuff 中的非法反射访问代码段

protostuff 中的非法反射访问代码段

这都是JDK基本模块的代码,因此,添加--add-opens=java.base/java.lang.invoke=ALL-UNNAMED即可。--add-opens可以使模块中的包对其他模块开放,这样就可以在运行期使用深层反射访问该程序包中的所有成员类型。

4. 总结

因此解决的办法是添加如下两个JVM参数:

--illegal-access=deny --add-opens java.base/java.lang=ALL-UNNAMED

IDEA可以在运行配置中的VM options中添加:

运行配置

如果使用Maven打包的时候还是会出现警告,可以在IDEA中的Maven配置中添加全局的Maven参数:

Maven 配置中添加全局的 Maven 参数

另外,如果使用Gradle而不是Maven作为管理工具,Gradle测试的时候还是会显示警告,尽管Gradle运行配置里面有VM Options选项:

Gradle 测试的时候还是会显示警告

但在这里添加是没用的,正确的做法是在build.gradle中添加:

test {
    useJUnitPlatform()
    jvmArgs('--illegal-access=deny')
    jvmArgs('--add-opens', 'java.base/java.lang.invoke=ALL-UNNAMED')
}

这样Gradle测试也没有问题了。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系maynote@foxmail.com处理
码云笔记 » JDK9以上的非法反射访问警告解决方法

发表回复