阿里妹导读
一、背景
为什么要升级JDK11
-
性能
-
JDK11的G1的GC性能高很多,对比JDK8无论是性能还是内存占比都有很大的提升,业内各项数据指标也都表明JDK11的G1在应对突发流量的下的效果惊人;
-
版本兼容
-
Spring Boot 2.7.x及以后的版本将不再支持Java 8作为最低版本。Spring Boot 2.6.x是最后一个正式支持Java 8的主线版本,一些新的中间件与组件也不再支持JDK8了; -
必然趋势
-
JDK11(LTS)已经成为业界主流,在Java开发社区和工业界中得到了广泛的接受和使用;
二、升级前你要知道的点
-
JDK11版本改动较大,且不会向下兼容。所以当你的业务代码越复杂,调用的链路越多,升级的难度越大。你会遇到很多兼容性问题,比如 二方包不支持新版本JDK;
-
JDK11移除了部分在Java 8就已经标记为过时的API例如sun.misc.Unsafe的部分方法,所以你的升级可能还涉及到代码的改动;
-
验证是个漫长而又耗时的过程,很多问题可能在运行时阶段才会暴露,你需要验证系统整体功能来保证系统稳定;
三、升级过程
本地升级,让你的JDK11跑起来
-
本地JDK11下载
-
IDEA选择JDK11启动
-
框架升级
<maven.compiler.target>11maven.compiler.target>
<maven.compiler.source>11maven.compiler.source>
<java.version>11java.version>
<spring-boot.version>2.1.6.RELEASEspring-boot.version>
<lombok.version>1.18.12lombok.version>
jdk11已移除,需手工依赖二方库
<dependency>
<groupId>javax.xml.soapgroupId>
<artifactId>javax.xml.soap-apiartifactId>
<version>1.4.0version>
dependency>
<dependency>
<groupId>com.sun.xml.wsgroupId>
<artifactId>jaxws-riartifactId>
<version>2.3.3version>
<type>pomtype>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-implartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>javax.xml.bindgroupId>
<artifactId>jaxb-apiartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>javax.annotationgroupId>
<artifactId>javax.annotation-apiartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>com.sun.activationgroupId>
<artifactId>javax.activationartifactId>
<version>1.2.0version>
dependency>
<dependency>
<groupId>com.sun.xml.bindgroupId>
<artifactId>jaxb-coreartifactId>
<version>2.3.0version>
dependency>
<dependency>
<groupId>com.alibaba.jvmgroupId>
<artifactId>java-migration-jdk-patchartifactId>
<version>0.3.1version>
<type>pomtype>
dependency>
<dependency>
<groupId>javax.transactiongroupId>
<artifactId>javax.transaction-apiartifactId>
<version>1.2version>
dependency>
-
遇到的问题
需要指定版本号
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.2.4.Finalversion>
dependency>
应用部署发布
-
使用G1垃圾回收器
去除
#SERVICE_OPTS="${SERVICE_OPTS} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSMaxAbortablePrecleanTime=5000"
#SERVICE_OPTS="${SERVICE_OPTS} -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly"
#SERVICE_OPTS="${SERVICE_OPTS} -XX:+ExplicitGCInvokesConcurrent -Dsun.rmi.dgc.server.gcInterval=2592000000 -Dsun.rmi.dgc.client.gcInterval=2592000000"
#SERVICE_OPTS="${SERVICE_OPTS} -XX:ParallelGCThreads=4"
#SERVICE_OPTS="${SERVICE_OPTS} -Xloggc:${MIDDLEWARE_LOGS}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
SERVICE_OPTS="${SERVICE_OPTS} -XX:+UseG1GC -XX:+UseVtableBasedCHA -XX:+UseCompactObjectHeaders"
SERVICE_OPTS="${SERVICE_OPTS} -XX:G1HeapRegionSize=8m"
SERVICE_OPTS="${SERVICE_OPTS} -XX:+G1BarrierSkipDCQ"
SERVICE_OPTS="${SERVICE_OPTS} -Xlog:gc*:/home/admin/logs/gc.log:time"
SERVICE_OPTS="${SERVICE_OPTS} -XX:G1HeapWastePercent=2"
SERVICE_OPTS="${SERVICE_OPTS} -XX:+ExplicitGCInvokesConcurrent -Dsun.rmi.dgc.server.gcInterval=2592000000 -Dsun.rmi.dgc.client.gcInterval=2592000000"
if [ -n "$AJDK_MAX_PROCESSORS_LIMIT" ]; then
SERVICE_OPTS="${SERVICE_OPTS} -XX:ActiveProcessorCount=$AJDK_MAX_PROCESSORS_LIMIT"
fi
GC调优的注意事项(数据来源JVM团队)
-Xmn参数一般不需要设置
-XX:NewRatio同理不需要设置
-XX:SurvivorRatio一般也不设置
升级G1后可能需要关注的参数
-XX:MaxGCPauseMillis=N,G1暂停的目标时间(毫秒)
-XX:InitiatingHeapOccupancyPercent=N -XX:-G1UseAdaptiveIHOP (电商核心使用)
-XX:G1HeapRegionSize,(电商核心通常使用8m-32m)
-XX:G1HeapWastePercent,(默认5,部分电商核心应用设置为2)
-XX:G1MixedGCCountTarget,Mixed GC目标次数,默认为8
升级G1的常见问题
CMS升级G1后,容器和Java进程内存占用变高
GC日志中To-space exhausted引起的异常暂停
GC过于频繁
Mixed GC暂停过长
四、升级效果
日常运行
压测效果
可以明显看到GC耗时降低了不少,速度快了70%左右
线上运行情况
从图中可以看到YGC的耗时明显缩短, 性能将近提升50%! 这归功于分代收集的能力
五、JDK11新玩法
字符串String加强