searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Spring boot 2.x升级JDK17

2023-03-29 06:56:00
272
0

背景

      目前大部分java运行的环境还是JDK8为主,JDK8是2014年发布的了,而且8u201/202 之后版本,oracle不在提供免费商用支持,JDK17于2021年09月14日发布,是最新的官方LTS(Long term support 长期支持),且商用免费,从相关基准测试来看,相比JDK8都有10%左右的提升,而且提供了新的低延迟ZGC,对G1也进行了很大的提升,这些特性,都让人想进行升级。

     本文基于spring boot 2.4 ,工程集成了MySQL5.7,mybatis plus,lettuce(redis 驱动) ,这些都是典型工程依赖,进行升级JDK17,看看期间会遇到那些坑。

升级步骤

     一:下载安装JDK17

     直接从oracle官方下载,注意OS和CPU版本  oracle JDK17

    装好后,需要配置JDK17的环境变量,这里由于大家工作中还是以JDK8为主,所以需要在开发环境工作保持2套JDK环境变量,这里作者的开发环境是mac os,一个类Linux系统。window和Linux开发环境的同学,可以提供一个思路,参考我的思路进行配置。

   打开bash 的source文件,进行配置:

# maven bin所在的目录
export M2_HOME=/Users/xxxx/Documents/dev_tool/apache-maven-3.5.2
      
# 将maven bin加到PATH变量中
export PATH=$PATH:$M2_HOME/bin
# 配置JAVA_HOME所在的目录,注意这个目录下应该有bin文件夹,bin下应该有java等命令
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home
export JAVA_11_HOME=/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home 08 export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
alias jdk8="export JAVA_HOME=$JAVA_8_HOME" #编辑一个命令jdk8,输入则转至jdk1.8
alias jdk11="export JAVA_HOME=$JAVA_11_HOME" #编辑一个命令jdk11,输入则转至jdk11
alias jdk17="export JAVA_HOME=$JAVA_17_HOME"
export JAVA_HOME=$JAVA_8_HOME
# MySQL config
export MYSQL_HOME=/usr/local/mysql
# add mysql config
export PATH=$PATH:$MYSQL_HOME/bin
# add gradle config
export GRD_HOME=/Users/xxxx/Documents/dev_tool/gradle-2.7
# add path
export PATH=$PATH:$GRD_HOME/bin
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH

备注:由于本人使用的事mac book m1芯片,所以是去zulu zuluJDK  下载了m1编译的版本,会比oracle的版本快一些,如果同学没有这个情况,还是推荐去oracle官网下载

这样,可以在命令窗口快速切换JDK

如果是idea,可以在IDE进行JDK配置,这里不在赘述。

二:使用JDK17重新编译运行

重新编译这个没啥好说,有了上面的环境变量快速切换,就可以切到jdk17,查看maven版本,就可以看到jdk环境,当然,如何你不像重新编译,理论也是可以运行的,这里我进行重新打包编译,工程代码没有做任何修改

重新编译后,直接运行,发现报错

 

1 解决模块报错

这个是由于 JDK9 之后,引入模块化导致的。 启动命令加上 :--add-opens java.base/java.lang=ALL-UNNAMED 即可,
如果是ide 需要在启动配置加上vm参数 (但是本次测试 需要打jar包启动,ide启动是散包)

java --add-opens java.base/java.lang=ALL-UNNAMED -jar monitordemo-1.0.0.jar   可以顺利启动

这里的模块化,没有很好的解决版本,需要根据自己工程中那些项目进行反射来决定,在现有的大量三方包,框架,还有一些自己组内的平台代码,都大量使用了反射,AOP技术,这里在JDK9 的模块化技术引入后,默认都是禁止的,需要在JVM启动参数进行声明,这里可以给一个我在多个项目实际运行的声明参数,大家可以加入自己的启动脚本,基本可以使用大部分场景

 

--add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED  --add-opens java.base/java.util.concurrent=ALL-UNNAMED   --add-opens java.base/java.util=ALL-UNNAMED  --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED

2 SSL协议问题

升级JDK17后,MySQL链接失败,出现如下报错:

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)


 原因是在JDK8_u292版本就移除了对 TLS1.0支持(见官方文档),所以在HTTPS,或者别的需要用到TLS加密请求的地方都会报错 ,JDK17是移除了,所以需要进行JRE配置修改:
在{JAVA_HOME}路径 /jdk-17.0.1/conf/security/java.security

找到

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ 
删除SSLv3, TLSv1, TLSv1.1, 改为 jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, \

可以用vi 进行搜索修改


修改后,重启即可

三:体验和测试对比

测试环境

mac os ,m1芯片,JDK 使用zulu-jdk-17,arm64版本

测试代码

比较简单:new 一千万对象,并且排序

1:使用G1

JDK17 默认就是G1 垃圾回收器,不用加额外参数
这个是默认的G1 GC ,从jstat -gcutil {pid} 1000 1000监控命令可以看出 ,还没有FGC ,大约每次YGC暂停1~400ms(默认参数)

使用命令行启动 30秒预热 ,new 对象 花了2.9秒,排序花了 0.9~1.2秒

 

CPU 波动较大,70~320%

2:使用ZGC

启动默认是G1 GC,如果要使用ZGC,需要在启动命令加入 -XX:+UseZGC  对于刚才的模块声明,启动命令就变成:
java --add-opens java.base/java.lang=ALL-UNNAMED -XX:+UseZGC -jar monitordemo-1.0.0.jar

jstat -gcutil {pid} 1000 1000 命令可以看到,ZGC 确实做到 <1ms 暂停,只有一个O区,没有分代

new对象花了2.5秒,排序花了 3.8~4.4秒,比G1 要差,这就是说的ZGC 吞吐会下降

CPU 约200%

3:使用JDK8 G1 编译运行

为了和JDK8对比,这里用JDK8 进行编译运行对比,由于JDK8没有ZGC,这里只在G1下进行对比

启动命令: java -XX:+UseG1GC -jar monitordemo-1.0.0.jar 表现不错,排序 1.3秒 new 对象 2.5秒

G1 gc 会有3~600ms 以内的暂停 ,该值可以进行设置,但是这里都使用默认值,所以不进行设置

4:简单结论

升级JDK17 可以带来更全面性能提升,G1的吞吐比ZGC要好。ZGC 可以做到<1ms 暂停

 

JDK17-G1

JDK-ZGC

JDK8-G1

排序一千万对象

0.9~1.2s  3.8~4.4s  1.1~1.4s

new一千万对

2.6~3.3s   平均  2.9s

2.4~2.9s  平均 2.6s

2.5~2.9s 平均2.8s

CPU  100~300% 100~200% 100~400%
YGC 时间 100~400ms <1ms 100~600ms
FGC暂停时间

 

 

0条评论
0 / 1000
张****钏
15文章数
1粉丝数
张****钏
15 文章 | 1 粉丝
原创

Spring boot 2.x升级JDK17

2023-03-29 06:56:00
272
0

背景

      目前大部分java运行的环境还是JDK8为主,JDK8是2014年发布的了,而且8u201/202 之后版本,oracle不在提供免费商用支持,JDK17于2021年09月14日发布,是最新的官方LTS(Long term support 长期支持),且商用免费,从相关基准测试来看,相比JDK8都有10%左右的提升,而且提供了新的低延迟ZGC,对G1也进行了很大的提升,这些特性,都让人想进行升级。

     本文基于spring boot 2.4 ,工程集成了MySQL5.7,mybatis plus,lettuce(redis 驱动) ,这些都是典型工程依赖,进行升级JDK17,看看期间会遇到那些坑。

升级步骤

     一:下载安装JDK17

     直接从oracle官方下载,注意OS和CPU版本  oracle JDK17

    装好后,需要配置JDK17的环境变量,这里由于大家工作中还是以JDK8为主,所以需要在开发环境工作保持2套JDK环境变量,这里作者的开发环境是mac os,一个类Linux系统。window和Linux开发环境的同学,可以提供一个思路,参考我的思路进行配置。

   打开bash 的source文件,进行配置:

# maven bin所在的目录
export M2_HOME=/Users/xxxx/Documents/dev_tool/apache-maven-3.5.2
      
# 将maven bin加到PATH变量中
export PATH=$PATH:$M2_HOME/bin
# 配置JAVA_HOME所在的目录,注意这个目录下应该有bin文件夹,bin下应该有java等命令
export JAVA_8_HOME=/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home
export JAVA_11_HOME=/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home 08 export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
alias jdk8="export JAVA_HOME=$JAVA_8_HOME" #编辑一个命令jdk8,输入则转至jdk1.8
alias jdk11="export JAVA_HOME=$JAVA_11_HOME" #编辑一个命令jdk11,输入则转至jdk11
alias jdk17="export JAVA_HOME=$JAVA_17_HOME"
export JAVA_HOME=$JAVA_8_HOME
# MySQL config
export MYSQL_HOME=/usr/local/mysql
# add mysql config
export PATH=$PATH:$MYSQL_HOME/bin
# add gradle config
export GRD_HOME=/Users/xxxx/Documents/dev_tool/gradle-2.7
# add path
export PATH=$PATH:$GRD_HOME/bin
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH

备注:由于本人使用的事mac book m1芯片,所以是去zulu zuluJDK  下载了m1编译的版本,会比oracle的版本快一些,如果同学没有这个情况,还是推荐去oracle官网下载

这样,可以在命令窗口快速切换JDK

如果是idea,可以在IDE进行JDK配置,这里不在赘述。

二:使用JDK17重新编译运行

重新编译这个没啥好说,有了上面的环境变量快速切换,就可以切到jdk17,查看maven版本,就可以看到jdk环境,当然,如何你不像重新编译,理论也是可以运行的,这里我进行重新打包编译,工程代码没有做任何修改

重新编译后,直接运行,发现报错

 

1 解决模块报错

这个是由于 JDK9 之后,引入模块化导致的。 启动命令加上 :--add-opens java.base/java.lang=ALL-UNNAMED 即可,
如果是ide 需要在启动配置加上vm参数 (但是本次测试 需要打jar包启动,ide启动是散包)

java --add-opens java.base/java.lang=ALL-UNNAMED -jar monitordemo-1.0.0.jar   可以顺利启动

这里的模块化,没有很好的解决版本,需要根据自己工程中那些项目进行反射来决定,在现有的大量三方包,框架,还有一些自己组内的平台代码,都大量使用了反射,AOP技术,这里在JDK9 的模块化技术引入后,默认都是禁止的,需要在JVM启动参数进行声明,这里可以给一个我在多个项目实际运行的声明参数,大家可以加入自己的启动脚本,基本可以使用大部分场景

 

--add-opens java.base/java.math=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED  --add-opens java.base/java.util.concurrent=ALL-UNNAMED   --add-opens java.base/java.util=ALL-UNNAMED  --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED

2 SSL协议问题

升级JDK17后,MySQL链接失败,出现如下报错:

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)


 原因是在JDK8_u292版本就移除了对 TLS1.0支持(见官方文档),所以在HTTPS,或者别的需要用到TLS加密请求的地方都会报错 ,JDK17是移除了,所以需要进行JRE配置修改:
在{JAVA_HOME}路径 /jdk-17.0.1/conf/security/java.security

找到

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \ 
删除SSLv3, TLSv1, TLSv1.1, 改为 jdk.tls.disabledAlgorithms=RC4, DES, MD5withRSA, \

可以用vi 进行搜索修改


修改后,重启即可

三:体验和测试对比

测试环境

mac os ,m1芯片,JDK 使用zulu-jdk-17,arm64版本

测试代码

比较简单:new 一千万对象,并且排序

1:使用G1

JDK17 默认就是G1 垃圾回收器,不用加额外参数
这个是默认的G1 GC ,从jstat -gcutil {pid} 1000 1000监控命令可以看出 ,还没有FGC ,大约每次YGC暂停1~400ms(默认参数)

使用命令行启动 30秒预热 ,new 对象 花了2.9秒,排序花了 0.9~1.2秒

 

CPU 波动较大,70~320%

2:使用ZGC

启动默认是G1 GC,如果要使用ZGC,需要在启动命令加入 -XX:+UseZGC  对于刚才的模块声明,启动命令就变成:
java --add-opens java.base/java.lang=ALL-UNNAMED -XX:+UseZGC -jar monitordemo-1.0.0.jar

jstat -gcutil {pid} 1000 1000 命令可以看到,ZGC 确实做到 <1ms 暂停,只有一个O区,没有分代

new对象花了2.5秒,排序花了 3.8~4.4秒,比G1 要差,这就是说的ZGC 吞吐会下降

CPU 约200%

3:使用JDK8 G1 编译运行

为了和JDK8对比,这里用JDK8 进行编译运行对比,由于JDK8没有ZGC,这里只在G1下进行对比

启动命令: java -XX:+UseG1GC -jar monitordemo-1.0.0.jar 表现不错,排序 1.3秒 new 对象 2.5秒

G1 gc 会有3~600ms 以内的暂停 ,该值可以进行设置,但是这里都使用默认值,所以不进行设置

4:简单结论

升级JDK17 可以带来更全面性能提升,G1的吞吐比ZGC要好。ZGC 可以做到<1ms 暂停

 

JDK17-G1

JDK-ZGC

JDK8-G1

排序一千万对象

0.9~1.2s  3.8~4.4s  1.1~1.4s

new一千万对

2.6~3.3s   平均  2.9s

2.4~2.9s  平均 2.6s

2.5~2.9s 平均2.8s

CPU  100~300% 100~200% 100~400%
YGC 时间 100~400ms <1ms 100~600ms
FGC暂停时间

 

 

文章来自个人专栏
java开发实践
6 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0