jdk的新特征
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升级
- 升级 maven 至推荐版本 3.5.0 (release)
- 升级 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
- Log4j 官方提供了 bridge 包进行平滑迁移,无需代码改动。但无法兼容编程配置方式、也无法支持访问 log4j 内部实现。
- 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
- 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 的参数有所变化
- -Xloggc:<logfile> 改为 - Xlog:gc:<logfile>
- 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
jdk 1.8
- lambda 表达式
- 方法引用
- 默认接口方法
- stream api
- 新的日期时间api
- type annotations 和repeatable annontations
- permGen 被移除
- nashorn javaScript引擎
jdk11
- 应用类数据共享 (application class-data sharing CDS)
- Espilon: 一种实验性Java 堆
- zgc: 一种实验时垃圾回收器
- 更快的数字字体渲染
- 增加了一个新的方法
- 启用了http/2的客户端
- 废弃了nashorn javaScript引擎
jdk 17
- sealed 类和接口
- 用与修复Java谷歌商店软件包在开源中无法构建的工具
- zgc垃圾回收器默认使用启动
- 新的编译器阈值
- vector api
- 提升线程
- 更加吸引人的事垃圾回收机制跟堆存储的唯一化
- 支持所有的嵌入式平台
- 颜文字支持
- 打开JRF文件的格式