JDK11 升级 JDK17 最全实践干货来了( 三 )


JDK11 升级 JDK17 最全实践干货来了

文章插图
原因:官方文档不鼓励循环依赖引用 , 默认情况下是禁止的
解决方案:
第一种:推荐更新应用中 bean 的依赖关系来解决
第二种:配置文件中加入以下配置 , 为了和旧版本保持一致,此配置推荐添加
#放开循环依赖
spring.mAIn.allow-circular-references=true
6.4、常用中间件升级
6.4.1、Lombok 版本升级到 1.18.20 以上
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
如果不升级,编译时会报错如下:
JDK11 升级 JDK17 最全实践干货来了

文章插图
6.4.2、swgger 问题,springfox3.0.0 和 springboot2.7 版本不兼容
异常:
Failed to start bean 'documentationPluginsBootstrApper'; nested exception is java.lang.NullPointerException:
Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
解决方案:
/**
* 增加如下配置可解决Spring Boot 2.7.15 与Swagger 3.0.0 不兼容问题
**/
@Bean
public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null).collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
参考:https://developer.aliyun.com/article/950787
6.4.3、AKS 升级(针对直接从 JDK8 升级的情况)
异常:Causedby: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
原因:Java11 删除了 Java EE modules,其中就包括 java.xml.bind (JAXB) 。
解决方案:
手动引入如下包即可
<!-- API, java.xml.bind module -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.2</version>
</dependency>
<!-- Runtime, com.sun.xml.bind module -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
6.4.4、Concrete 配置中心阻塞升级
使用 Concrete 时,启动时异常:
Unable to make field private static final java.lang.reflect.Method jdk.proxy2.$Proxy97.m0 accessible:
module jdk.proxy2 does not "opens jdk.proxy2" to unnamed module @61d47554
原因:
分析下 Concrete 报错的原因,如下图,包内 com.wangyin.concrete.spring.ConcreteConfigProcessor#postProcessAfterInitialization(212 行)的实现逻辑
JDK11 升级 JDK17 最全实践干货来了

文章插图

JDK11 升级 JDK17 最全实践干货来了

文章插图
解决方案:
1、在 JVM 启动参数中设置 --add-opens jdk.proxy2 来开启私有字段的访问,但因为动态代理生成的包名是随机不明确的,所以这种方案不可行 。JDK 官方文档也明确表示不支持访问动态代理内部的随机字段 。官方说明:https://cr.openjdk.org/~mr/jigsaw/spec/api/java/lang/reflect/Proxy.html
2、代码修改,只需把 f.setAccessible (true) 移到 Modifier.isStatic (f.getModifiers ()) 的判断下方即可 。原因是方法 Modifier.isStatic (f.getModifiers ()) 本来就要跳过静态字段,这样修改直接避免了访问 。推动 concrete 团队修复问题或更换使用 Ducc 配置中心
6.5、JVM 启动参数配置
6.5.1、开启 ZGC
启动参数中配置:-XX:+UseZGC


推荐阅读