随着SpringBoot2.7的发布,支持jdk8~jdk21。Springboot3.X发布,最低需要jdk17。升级jdk17是大势所趋。
参考1:重磅!Spring Boot 2.7 正式发布、
参考2:hutool-希望Hutool能支持下JDK8~JDK17的所有版本
由于jdk9增加的模块化设计,导致对系统内置类反射受到限制,出现类似的错误,自己开发的类没有影响。
public static void main(String[] args) {
// jdk17使用反射,无需修改,可以正常使用示例
NucPerson nucPerson = new NucPerson();
nucPerson.setPersonName("张三");
ReflectUtil.setFieldValue(nucPerson, "personPhone", "18800001111");
System.out.println(nucPerson.getPersonPhone());
System.out.println(ReflectUtil.getFieldMap(NucPerson.class));
// jdk17使用反射系统模块的类,必须要增加--add-opens的反射示例
Object stringValue = ReflectUtil.getFieldValue(nucPerson.getPersonName(), "value");
System.out.println(stringValue);
}
java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.Map sun.reflect.annotation.AnnotationInvocationHandler.memberValues accessible: module java.base does not "opens sun.reflect.annotation" to unnamed module @52d455b8
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na]
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na]
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178) ~[na:na]
at java.base/java.lang.reflect.Field.setAccessible(Field.java:172) ~[na:na]
at cn.hutool.core.util.ReflectUtil.setAccessible(ReflectUtil.java:966) ~[hutool-core-5.7.19.jar:na]
at cn.hutool.core.util.ReflectUtil.getFieldValue(ReflectUtil.java:266) ~[hutool-core-5.7.19.jar:na]
at cn.hutool.core.util.ReflectUtil.getFieldValue(ReflectUtil.java:234) ~[hutool-core-5.7.19.jar:na]
at cn.hutool.core.annotation.AnnotationUtil.setValue(AnnotationUtil.java:215) ~[hutool-core-5.7.19.jar:na]
解决:增加jvm启动参数(java虚拟机启动参数)
--add-opens java.base/sun.reflect.annotation=ALL-UNNAMED
汇总:
-Djdk.home=/Library/Java/JavaVirtualMachines/openjdk-18.0.1.1/Contents/Home
-Xms24m
-Xmx768m
-DTopSecurityManager.disable=true
--add-exports=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED
--add-exports=java.desktop/sun.awt=ALL-UNNAMED
--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor.event=ALL-UNNAMED
--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED
--add-exports=java.desktop/sun.swing=ALL-UNNAMED
--add-exports=jdk.attach/sun.tools.attach=ALL-UNNAMED
--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED
--add-opens=java.desktop/javax.swing.plaf.synth=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
--add-opens=java.base/java.lang.ref=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.desktop/javax.swing=ALL-UNNAMED
--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED
-XX:+IgnoreUnrecognizedVMOptions
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/Users/duandazhi/Library/Application Support/VisualVM/2.1.2/var/log/heapdump.hprof
--add-opens
和--add-exports
区别,opens是深度反射,可以打开对私有变量、成员的反射;exports只能打开公有变量的反射。总结:使用--add-opens
肯定没问题。
总结:模块化需要增加的JVM打开反射参数,对常规业务系统影响不大,毕竟对系统类反射操作很少,对自己开发的类进行反射操作并没有限制。
高版本最坑应该是这一条:
Java 11 :移除JavaEE和CORBA模块
对于Java EE和CORBA模块在Java 9开始就不推荐使用了。而从Java 11开始正式删除了这部分内容,所以当升级到Java 11或更高的版本的话,务必要先更急以下内容相关的代码:
移除的包:
移除的工具:
不过,我看也有办法,我的项目里面就使用到了webservice,即:jaxb
(实体类和xml转换)、soap
webservice的http网络请求。
受到影响的hutool工具类cxf相关:JAXBUtil
、SoapClient
;
业务场景,系统请求外部接口使用是webservice,实体类和xml转换需要用JAXBUtil、发送Http请求使用SoapClient
<!-- 适配jdk升级到9及以上,移除了 javax.xml.bind (JAXB) 的问题; javax需要从外部引入 -->
<!-- https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api -->
<!-- java.xml.bind 模块的接口 API -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.4.0-b180830.0438</version>
</dependency>
<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
<version>2.1.2</version>
</dependency>
<!-- 适配jdk升级到9及以上,java.lang.NoClassDefFoundError : javax/xml/soap/SOAPException-->
<!-- create SAAJ meta-factory: Provider com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl not found-->
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>javax.xml.soap-api</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.messaging.saaj</groupId>
<artifactId>saaj-impl</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>