Docker设置JDK17的JVM启动参数踩坑

背景

需求中需要接入某平台的广告SDK,在编写完代码进行自测时,直接报错,提示

Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass
堆栈信息如下

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @7ce026d3
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)

解决

然后直接在网上搜索了一下这个报错信息,了解到,这是由于 Java中有关反射相关的功能自从 JDK9 就开始进行了限制,因此如果还想继续在JDK9以及更高的版本中使用反射相关的功能,需要添加JVM启动参数, --add-opens java.base/java.lang=ALL-UNNAMED 。目前的项目使用的是JDK17,所以加了这个参数之后,可以直接在IDEA里正常启动项目,如下所示:

image-20230313115155465

由于现在的项目都是用Docker部署的,所以紧接着在DockerFile中添加了这个JVM启动参数,如下所示:

image-20230313115316766

但是Docker在启动项目的时候又报错了

Unrecognized option: --add-opens java.base/java.lang=ALL-UNNAMED
2023-03-13T03:54:39.098594714Z Error: Could not create the Java Virtual Machine.
2023-03-13T03:54:39.098656798Z Error: A fatal exception has occurred. Program will exit.

image-20230313115520005

--add-opens java.base/java.lang=ALL-UNNAMED这个参数JVM竟然识别不出来,什么鬼?

于是接着搜索,终于在一个帖子里找到了答案

image-20230313115826802

原来是因为JVM并不能识别参数中的空格,所以正确的参数应该是:

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

使用上面的参数进行设置后,Docker可以正常部署项目了。真的是醉了,真的是,国内的博客一个个都是复制粘贴,就没一个靠谱的。

参考

Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass
hotspot doesn't recognise new jigsaw options passed through _JAVA_OPTIONS

posted @ 2023-03-13 12:09  Reecelin  阅读(2871)  评论(0编辑  收藏  举报