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
里正常启动项目,如下所示:
由于现在的项目都是用Docker
部署的,所以紧接着在DockerFile
中添加了这个JVM
启动参数,如下所示:
但是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.
--add-opens java.base/java.lang=ALL-UNNAMED
这个参数JVM
竟然识别不出来,什么鬼?
于是接着搜索,终于在一个帖子里找到了答案
原来是因为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