问题描述
今天 在 install Maven项目的时候,控制台出现警告如下:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.thoughtworks.xstream.core.util.Fields (file:/E:/DevelopmentKit/Maven/install-location/apache-maven-3.8.1-bin/localRepository/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar) to field java.util.Properties.defaults
WARNING: Please consider reporting this to the maintainers of com.thoughtworks.xstream.core.util.Fields
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
字面意思说的是发生的了一个非法的反射访问操作,警告发生的地方是:
从com.thoughtworks.xstream.core.util.Fields (file:/E:/DevelopmentKit/Maven/install-location/apache-maven-3.8.1-bin/localRepository/com/thoughtworks/xstream/xstream/1.3.1/xstream-1.3.1.jar) 到 field java.util.Properties.defaults存在非法的反射访问。
1
问题分析
想了很久也没有弄明白是什么原因导致了控制台输出了这个警告,后面在网上查了查资料,发现是这么一回事:在JDK 9之前 ,Java允许通过反射机制访问所有的成员,这些成员的类型包括私有(private),公共(public),包(< package >)和受保护(protected)。JDK9新增的功能之一 —— 模块系统对反射的行为做出了一定的限制。
从JDK9开始,对于非公有的成员、成员方法和构造方法,模块不能通过反射直接去访问,但是JDK9提供了一个可选的修饰符open来声明一个开放模块,可以从一个开放模块中导出所有的包,以便在运行时对该模块中的所有包中的所有类型进行深层反射来访问。
在JDK9中,Java运行时由一个一个的模块组成。基于旧版本JDK开发的第三方jar包在迁移到JDK9时无法被转换成为模块,但是可以将其放在类路径下,被加载成为一个unnamed标识的模块,如果该模块存在被使用的需求,则会被放置在模块路径上,被加载后用作自动模块,进而被系统依赖使用。
问题解决
从上面的分析可以知道,处理该警告的解决方法主要存在以下两种:
方案一:将JDK切换成旧版本的。(我这里使用的是JDK11出现了这个问题,将JDK11降级成JDK8之后警告就消失了)
具体操作:
1.打开项目结构
2.做出以下修改。
3.点击保存
方案二:使用 --illegal-access 参数
其实这个参数在控制台输出的信息中已经给出了,如下
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
其常用的参数值如下:
permit 默认行为,允许通过反射进行访问。当第一次尝试通过反射进行非法访问时会生成一个警告,之后不会再进行警告。
warn 与permit相同,但每次非法访问时都会产生警告。其大致等效于 “–permit-illegal-access”。
debug 每次非法访问产生警告的同时打印非法访问的堆栈跟踪信息。
deny 不允许所有的非法访问操作,除了启用其它命令行参数排除的模块,例如"–add-opens",这个参数可以参数将某些模块排除出来,让它们能够通过非法反射进行访问。
为了消除警告并继续使用需要进行非法访问的模块,可以将参数 --illegal-access的值设置为deny并使用一个或多个`–add opens 来打开对应的模块允许对其进行非法反射访问。
具体的做法如下:
①点击settings 并打开到如下的页面。
②修改完成后点击OK。
要注意的是 :
参数 --add-opens java.base/java.base模块内的jar包名 = ALL-UNNAMED
1
java.base模块内的jar包有很多,比如java.lang、java.util等等
具体包括哪些,可以参考这篇博客:https://blog.csdn.net/ixiaoyang/article/details/103814792
笔者根据控制台的警告信息,在"java.base模块内的jar包名"处填写的是 java.util.Properties.defaults包在java.base模块内对应的jar包,即 java.util包(感觉这样会比较保险),当然填写其他的好像也可以(前提是在java.base模块内,但是没弄懂具体是什么回事)。.
如果指定的包不在java.base模块内,控制台会输出如下的警告: