jdk的新特征

发布时间 2023-07-14 11:12:25作者: 那一的眸相遇

jdk11新特征:

 

https://my.oschina.net/u/4662964/blog/5783779

 

依赖升级: 

在 JDK8 中 JavaSE 和 JavaEE 有很多共享代码,但是 JDK11 中这两部分独立了,JavaEE 相关模块被移除,无法编译,因此需要添加包括这些包的第三方依赖

如:编译时 @Resource/@PostConstruct 等注解找不到,需要显式引入 javax.annotation

 
<dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.2</version>
    </dependency>

maven升级

  1. 升级 maven 至推荐版本 3.5.0 (release)
  2. 升级 maven-compiler-plugin 到 3.8.0 以上,同时指定编译的目标文件和源文件的编译版本
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
      <source>11</source>
      <target>11</target>
    </configuration>
</plugin>

 

spring升级

由于 Spring 4.x 最多只支持到 JDK 8,因此若要升级 JDK 11,建议同时升级 Spring 至 5.x 版本

附 Spring 各版本支持的 JDK 版本范围

Spring Framework 6.0.x: JDK 17-21 (expected)

Spring Framework 5.3.x: JDK 8-19 (expected)

Spring Framework 5.2.x: JDK 8-15

Spring Framework 5.1.x: JDK 8-12

Spring Framework 5.0.x: JDK 8-10

Spring Framework 4.3.x: JDK 6-8

 

废弃了 ref load 标签

spring 5.2.0 无法扫描非Runtime 注解

问题:线上压测时发现 某个二方库的本地缓存失效,导致下游依赖 QPS 大幅上涨。



原因:Spring 5.2.x 只能找到 @Retention (RetentionPolicy.RUNTIME) 的自定义注解,应用依赖的二方库中有非 RUNTIME 的注解,
因此与 5.2.x 及以上版本不兼容。导致依赖注解扫描加载的富客户端本地缓存代理类 无法被加载,缓存失效,才会导致大量请求打到远端服务。

 

log4j 的兼容、升级

两种解决方案:
升级 Log4j2(推荐)
手动使 Spring 5.x 兼容 Log4j 1.x,建议仅在依赖二方包无法平滑迁移 Log4j 2 情况下使用(不推荐)

升级 Log4j 2.x

  1. Log4j 官方提供了 bridge 包进行平滑迁移,无需代码改动。但无法兼容编程配置方式、也无法支持访问 log4j 内部实现。
  2. slf4j 版本 和 log4j-slf4j-impl 版本需要同步
    log4j-slf4j-impl should be used with SLF4J 1.7.x releases or older.log4j-slf4j18-impl should be used with SLF4J 1.8.x releases or newer. ref
  1. log4j 2 不支持 Servlet 2.4 ref , 需要升级到 Servlet 3.0。

兼容 Log4j 1.x

 

若依赖的二方库使用 Log4j 1.x 导致应用无法通过官方适配包平滑迁移到 Log4j2,可以自行实现 Log4jConfigListener 初始化 log4j,使 Spring 5.x 兼容 Log4j1.x

验证日志是否正确输出时需要注意,相比于 Spring 4.x,Spring 5.x 部分日志级别有所调整。

 

Log4jConfigListener 实现参考:(见文末附录)

 

 

 GC 升级

JDK11 在 GC 上有一些值得注意的变化,包括:
默认 GC 由 CMS 换成 G1
废弃了多种 GC 组合 和 GC 参数。
所有 GC 策略 GC log 打印出的文本格式发生了变化,和 JDK8 不兼容。
  • GC 参数

GC log 参数改变JDK11 中打印 GC log 的参数有所变化
  1. -Xloggc:<logfile> 改为 - Xlog:gc:<logfile>
  2. JDK11 中不再支持 -XX:+PrintGCDetails,PrintGCDateStamps

    若使用了 -XX:+PrintGCDetails,将 - Xlog:gc:<logfile> 改成 - Xlog:gc*:<logfile>.若使用 -XX:+PrintGCDateStamps,在 - Xlog:gc:<logfile> 后面添加:time,即修改为 - Xlog:gc:<logfile>:time.
废弃 GC 参数具体废弃参数可参考:https://www.oracle.com/java/technologies/javase/9-removed-features.html

  • GC 算法升级

G1 和 ZGC 的特点及适用场景见后文新特性中关于 GC  的介绍

 

 

配置调优参数

G1 配置和调优参数可参考:https://www.oracle.com/technical-resources/articles/java/g1gc.html

ZGC 配置参数

-XX:+UnlockExperimentalVMOptions 
-XX:+UseZGC
具体调优参数参考:https://docs.oracle.com/en/java/javase/11/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0


应用升级后单机 GC 性能压测表现


日常水位 GC 统计数据

 

 

 JDK 11 + ZGC 压测时,在 400 QPS 时 RT 和 CPU 开始不正常飙高,经分析 ZGC 由于不分代,适合老年代对象较少的场景,而本应用有大量常驻内存的对象,所以不适合使用 ZGC