前言
最近在给公司新架构做技术选型,刚好 Java 17 也正式发布一段日子了,而且是
LTS
长期支持版本,就想着直接用起来吧,里面有些特性还是非常好用的,比如:
遇到的问题
1 |
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 @39aeed2f |
从 Java 16 开始,
JEP 396
会默认把
--illegal-access
参数设置为
deny
,即默认禁用访问封装的包以及反射其他模块,这样就会导致上面的异常,在此之前该参数默认值一直都是
--illegal-access=permit
,只会产生警告,而不会报错,所以如果是 Java 16 的话需要在执行 Java 程序时把
--illegal-access
设置为
permit
,这样就可以解决问题,示例:
1 |
java -jar --illegal-access=permit app.jar |
从 Java 17 开始就更狠了,
JEP 403
直接把
--illegal-access
参数移除了,如果需要启用访问封装的包,需要在执行 Java 程序时加上
--add-opens java.base/java.lang=ALL-UNNAMED
选型,示例:
1 |
java -jar --add-opens java.base/java.lang=ALL-UNNAMED app.jar |
如果是在 IDEA 中运行需要配置对应的 VM 参数,示例:
虽然说加完参数之后是可以跑起来,但是我认为这是一个破坏性的改动,因为这样的话,如果有一天 Java 版本变化了,参数又失效了,那么所有的项目都需要更新,这样会导致项目的维护成本大大增加,所以这里不建议使用。
开源框架升级进度跟踪
那么有没有办法不加启动参数就能正常运行呢,答案是肯定的,只不过需要等开源框架全换算 Java 17 的新 API,目前我跟踪到的两个项目都还没有适配 Java 17。
Spring
SpringBoot 2.5.0 开始支持 Java 17,没啥问题。
apollo 配置中心
apollo 目前的 master 分支代码是已经适配好了,但是还没有正式发版,比较奇怪的事是, apollo 之前 升级 了底层依赖包来适配 Java 17,但是后来又 回滚 回来了,不知道是出于什么原因。
dubbo
dubbo 有个 issue 7593 四月份就提出来了,但是一直没人跟进。