为什么要升级
业界
- Oracle Java 8 的 Support 已经到期,目前每两年出 1 个 LTS 版本,发布节奏快
- Spring、Netty、Jetty、Kafka 等在 Java 生态非常流行的软件逐渐不兼容 JDK8
- 从相对权威的生态报告上看,JDK11 的使用占比超过了 JDK8
升级带来的好处
- 相对JDK 8,11/17 有超过 100+ 新特性,覆盖性能、安全、语法等多个角度
- 性能方面,在内存、GC、RAS、启动以及新架构 AArch64领域都有明显的优化
- 对云原生支持更友好,包括 Serverless Java Runtime启动更快,JFR可观测性更优及更多容器支持
新版JDK的特性
-
压缩String(JDK9)
String 底层结构优化,使用 byte[],提高内存利用率
-
CodeCache(JDK9)
除了hotspot中的JIT(C1、C2)外,还有解释器也会生成动态代码
所有生成的代码会存储在CodeCache里,按照类型划分在不同的区域里,利用cache的局部性对指令进行缓存
进而降低内存碎片
-
可伸缩元空间(JDK16)
降低元空间使用率和碎片化,将空闲的空间归还给OS
-
G1(JDK9)
高吞吐量、低延迟的GC实现
-
统一的GC日志(JDK9)
-
高性能的JFR(JDK11)
超低开销下的JVM可观测性能力
关联分析实现方法、对象分配、IO、锁竞争等多维度的热点分析 -
更精准的NP报错(JDK4)
在a.b.c这样的链式调用情况下,能更清晰的给出报错的信息
-
模块化(JDK9)
目前来看,用处不大
升级挑战
以下是从JDK 8升级到JDK 11会遇到的一些困难:
1.移除的API和功能:自JDK 9以来,一些API和功能已经被弃用并最终在JDK 11中移除,例如Nashorn JavaScript引擎和Java Applets。
2.模块化系统:JDK 9引入了Java平台模块系统(JPMS),这可能会导致依赖问题,需要重新组织代码和库依赖。
3.第三方库和框架的兼容性:可能会遇到第三方库或框架与JDK 11不兼容的情况。需要检查和升级这些依赖项。
4.性能问题:新版本可能会引入性能变化,需要对应用程序做性能测试和调优。
5.工具和插件支持:开发和构建工具可能需要更新以支持JDK 11,例如Maven或Gradle。
6.新的垃圾收集器:JDK 11引入了新的垃圾收集器,例如ZGC和Epsilon。需要理解这些新特性并根据需要调整JVM参数。
7.语法和特性变更:虽然从JDK 8到JDK 11的源代码兼容性相对较好,但一些新特性和改进(如本地变量类型推断)可能需要代码更改来充分利用。
8.安全性和TLS:JDK 11提高了安全性要求,包括对TLS的更新,可能需要调整安全配置。
9.升级成本:升级可能涉及代码更改、测试和部署,这些都增加了工作量和成本。
为了成功升级,您需要执行以下步骤:
- 更新并测试所有的依赖项以确保兼容性。
- 使用JDK 11重新编译代码并处理任何编译错误。
- 对应用进行彻底测试,包括单元测试、集成测试和性能测试。
- 阅读JDK 8到JDK 11之间所有版本的发布说明,了解重要更改和潜在的影响。
- 考虑使用工具(如jdeps)分析依赖关系和模块。
升级总是需要仔细规划和执行,但从长远来看,迁移到更现代的Java版本可以带来更好的性能、新特性和改进的安全性。
如何升级
二方包打包问题
jdk11的项目打出来的二方包,为了给其他jdk8的项目用,需要将打出来的包的级别设置为jdk8
在 pom中设置 变量 maven.compiler.source 为8 即可
基础环境配置
- maven需要升级到3.5.0以上,maven-compiler-plugin升级到3.6.1以上
待升级的maven项目的pom配置如下
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
- Idea 版本要求:intellij版本在2018.2以上
- Idea的JDK也要升级(使用Idea自己的JDK版本管理功能,下载jdk11即可)
- Spring 升级
JDK11对于spring最低版本要求是5.0 - GC参数改变
SERVICE_OPTS="${SERVICE_OPTS} -XX:+UseG1GC"
SERVICE_OPTS="${SERVICE_OPTS} -XX:G1HeapRegionSize=8m"
SERVICE_OPTS="${SERVICE_OPTS} -XX:+G1BarrierSkipDCQ"
SERVICE_OPTS="${SERVICE_OPTS} -XX:ErrorFile=/home/admin/logs/hs_err_pid%p.log"
SERVICE_OPTS="${SERVICE_OPTS} -Xlog:gc*:/home/admin/logs/gc.log"
# SETENV NEW OPTS
SERVICE_OPTS="${SERVICE_OPTS} -XX:ReservedCodeCacheSize=256m"
SERVICE_OPTS="${SERVICE_OPTS} -noverify -DdefaultHsfClientTimeout=3000 -Dpandora.ignore.packaged.plugins=false"
SERVICE_OPTS="${SERVICE_OPTS} -Djava.awt.headless=true -Dcom.sun.management.jmxremote.port=1090 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=$LOCAL_IP"
SERVICE_OPTS="${SERVICE_OPTS} --add-exports java.base/jdk.internal.ref=ALL-UNNAMED"
- 无效的包,需要排除
- 框架版本要求
ASM >= 7.0
Guice >= 4.2
guava >= 18.0
lombok >= 1.18.22
MapStruct >= 1.5.5.Final
Kotlin >= 1.3.30
dagger >= 2.24
Mockito >= 2.22.0
Jacoco >= 0.8.3
JMockit >= 1.49
aspectj >= 1.14.0
groovy >= 2.5.6
升级常见问题
- 缺少javax相关的包
JDK11及以上版本,已经没有这些rt.jar了,而用.so文件代替了.
添加依赖
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.1</version>
</dependency>
- lombok问题
升级lombok版本到1.18.22及以上版本.
- 无法远程debug
JDK11的DEBUG端口变成了*:PORT的SOCKET形式.
将
-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n
改为
-agentlib:jdwp=transport=dt_socket,address=*:8000,server=y,suspend=n
参考
1、https://grow.alibaba-inc.com/course/4800015674472669/section/1800015674472769
2、https://ata.atatech.org/articles/11020147240?spm=ata.23639746.0.0.753d21b8aGbM4p
3、https://ata.atatech.org/articles/11020153233