JDK8 到 JDK11 版本迁移指南 - Tencent/TencentKona-11 GitHub Wiki
本文档旨在帮助由 Tencent Kona JDK 8 迁移至 Tencent Kona JDK 11 的工程师,评估和发现可能的兼容问题,并提供相应解决建议和经验,如果您想了解迁移到 JDK 11 的业务价值,请参考 Tencent Kona 团队的相关分享。
本文档主要内容包括:
- JDK 11 功能和结构变化
- JDK 打包类库的变化
- JVM GC 等基础机制变化
- 具体的 step-by-step 迁移指导
注意:
- 考虑到生产实际,本文对比基于 Tencent Kona JDK 11 vs Tencent Kona JDK 8,对比项细节将明确标记出
- 本文列出的是可能的兼容性影响,因此会更加集中于原有功能的移除和修改,而不会侧重介绍 ZGC 等新特性
事项
|
文件结构变化
|
说明
|
|
---|---|---|---|
JDK配置文件 |
将散落在JDK各个子目录的配置文件,例如安全策略配置等,都集中到新添加的conf目录下
|
请检查应用是否有对相关配置的依赖 | |
JRE | ${JAVA_HOME}/jre被移除 | ||
ClassLoader扩展机制 | ${JAVA_HOME}/lib/ext被移除 | ExtClassloader目前被重构为PlatformClassloader,并且类型不再是URLClassloader | |
javah | ${JAVA_HOME}/bin/javah被移除 |
可以使用 javac -h |
|
Corba相关工具 |
|
||
Web Service相关工具 |
|
JDK 9引入的JPMS,以及对JDK自身进行的重构,往往是最大的兼容性难点来源,模块化引入的封装,虽然提供了隔离性、安全性等好处,但随之而来的Readability和Accessability也会影响一些基础机制:
-
应用运行时反射访问Java public/internal API,可能被禁止,解决办法是
// 也可以设置 deny 或 warn 来进行排查 --illegal-access=permit // 或者使用 --add-open 来解决反射 accessiblity 限制 // 例如: java --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED -jar jython-standalone-2.7.0.jar
-
应用代码引用非Java Public API,则会面临编译期和运行时两个阶段的兼容问题
// 可以使用下面的命令给javac或者java命令,解决编译期/运行时困难 --add-exports java.management/sun.management=ALL-UNNAMED
虽然是 Internal API,但当时很多开源软件和应用对此有依赖,从 ProtoBuf、netty 再到 Cassandra,都难以避免,最好的办法是去查找相关项目的 JDK 11 支持版本。
- Unsafe.monitorEnter()/monitorExit 等 API 被移除,可以使用 concurent API 替代
- Base64Encoder/Decoder 等可以替换为 java.util.Base64
- 其他一些能力被 VarHandle API 取代,更加安全和强大
这些都是 JDK 9 中即标记过时(Deprecated)的类库,从业界移植经验看总体影响非常有限。
- java.xml.ws: Java API for XML Web Services (JAX-WS)
- java.xml.bind: Java Architecture for XML Binding (JAXB)
- java.xml.ws.annotation
- java.corba: CORBA
- java.transaction: Java Transaction API的子集,以支持CORBA Object Transaction Services
- java.activation: JavaBeans Activation Framework
- java.se.ee: 它是一个聚合模块,包含以上6个模块
- jdk.xml.ws: JAX-WS工具
- jdk.xml.bind: JAXB工具
如果产品恰好有相关依赖,仍然可以在 Maven Central 获得相关模块,请参考 JEP 320: Remove the Java EE and CORBA Modules
从 JDK 9 开始,OpenJDK 默认 GC 已经替换为 G1 GC,JDK 8 则是 Parallel GC,兼容性影响主要体现在:
- G1 GC 的 Memory Overhead 略高、初始化时间略长(总体影响应该是在 ms 级别,通常不会影响到生产负载)
绝大部分应用会自己指定 JVM GC 等参数,所以通常不会有明显影响,JDK 11 的 G1 GC 相比 JDK8,在吞吐量和延迟等方面甚至有很大提升,但仍需进行实际业务验证,以确保是否有特定场景的 regression。
gc log的参数设置也发生了变化
旧参数 | 新参数 |
---|---|
PrintGC | -Xlog:gc |
PrintGCDetails | -Xlog:gc* |
PrintGCApplicationConcurrentTime PrintGCApplicationStoppedTime | -Xlog:safepoint |
PrintGCCause | 不需要加格外参数,开启gc tag就有 |
PrintGCDateStamps | decorators里设置 |
PrintReferenceGC | -Xlog:ref*=debug |
PrintHeapAtGC | -Xlog:gc+heap=trace |
PrintAdaptiveSizePolicy | -Xlog:ergo*=debug |
G1PrintHeapRegions | -Xlog:gc+region=trace |
PrintTenuringDistribution | -Xlog:gc+age*=trace |
ZGC 的堆申请和传统的 GC 有所不同,需要占用的 memory mapping 数目更多,即每个 ZPage 需要 mmap 映射三次,这样系统中仅Java Heap 所占用的 mmap 个数为 (xmx / zpage_size) * 3,默认情况下 zpage_size 为 2M。
而为了给 jni 等 native 模块 mmap 映射留出空间,内存映射的数目应该调整为 (xmx / zpage_size) * 3 * 1.2。
默认的系统 memory mapping 数目由文件 /proc/sys/vm/max_map_count 指定,通常数目为 65536,当给 JVM 配置一个很大的堆时,需要调整该文件的配置,使得其大于 (xmx / zpage_size) * 3 * 1.2。
-
获取 Tencent Kona JDK 11 最新版本
-
使用 java 11
`jdeps --jdk-internals -R --class-path 'libs/*' $project`
-
尝试运行应用程序,发现可能的兼容问题
-
如果有,则尝试解决兼容问题:
- 参考上一章节调整 JVM 参数等
- 升级第三方软件包
- 尝试重新编译
-
运行和测试应用程序