jdk 11 非法反射警告的处理

问题产生:


WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by **YOUR PACKAGE** (file: **YOUR FILE** ) to field java.util.Collections$UnmodifiableMap.m
WARNING: Please consider reporting this to the maintainers of **YOUR PACKAGE**
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

解决办法:


1.降级到jdk8

2.启动类,增加忽略非法反射警告的办法

@SpringBootApplication
public class XxxxApplication {
 
    public static void main(String[] args) {
        // 调用方法
        disableAccessWarnings(); // 忽略非法反射警告
        SpringApplication.run(XxxxApplication .class, args);
    }
 
    /**
     * 忽略非法反射警告 适用于jdk11
     */
    @SuppressWarnings("unchecked")
    public static void disableAccessWarnings() {
        try {
            Class unsafeClass = Class.forName("sun.misc.Unsafe");
            Field field = unsafeClass.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            Object unsafe = field.get(null);
 
            Method putObjectVolatile =
                unsafeClass.getDeclaredMethod("putObjectVolatile", Object.class, long.class, Object.class);
            Method staticFieldOffset = unsafeClass.getDeclaredMethod("staticFieldOffset", Field.class);
 
            Class loggerClass = Class.forName("jdk.internal.module.IllegalAccessLogger");
            Field loggerField = loggerClass.getDeclaredField("logger");
            Long offset = (Long)staticFieldOffset.invoke(unsafe, loggerField);
            putObjectVolatile.invoke(unsafe, loggerClass, offset, null);
        } catch (Exception ignored) {
        }
    }
}

3.配置JVM 的参数

--illegal-access

该参数有四个可选值:

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

要验证您的应用程序是否已为 JDK 的未来版本做好准备,请将它--illegal-access=deny与任何必要的--add-opens选项一起运行。任何剩余的非法访问错误很可能是由于从编译代码到 JDK 内部 API 的静态引用。您可以通过运行带有该选项的工具来识别这些--jdk-internals。出于性能原因,当前的 JDK 不会对非法静态访问操作发出警告。

--add-opens

只能在包级别打开模块:

--add-opens module/package=target-module(,target-module)*

范例:(1) 由于java.util.Collections属于模块中的中的java.util包,因此必须添加JVM参数

--add-opens java.base/java.util=target-module(,target-module)*

(2)目标模块必须是要访问java.util.Collections$UnmodifiableMap.m或ALL-UNNAMED模块的模块

--add-opens java.base/java.util=ALL-UNNAMED

经验分享 程序员 微信小程序 职场和发展