Spring Boot 近日发布了第一个里程碑版本:Spring Boot 3.0.0-M1 主要JDK版本:JDK8 → JDK17,JetBrains博客也显示:Intelij项目的源代码迁移到了Java 17,这也是释放一个信号,我们是不是应该考虑升级了。以前只看到JDK的版本成指数上升🔝,但是依然它升任它升,万年Java8,现在可能是一次临门一脚的机会,做一些改变,拥抱新的开始,绘画新的蓝图,但是我们应该使用哪个Java版本?
上图可以看到JVM在各地发展的情况,在互联网的时代中,我们有数以万计的java开发人员,总共有30亿多个JVM在跑,作为庞大群里中的一员,他们并不关心外部分布,依然坚持自己使用的Java版本,只能说毅力惊人,今天其实可以开始考虑,只要正在做的东西可以从新的JDK版本中受益,那不妨升级一下还是有用的。一般升级JDK的人会来自两种人
- 疯狂升级版本
- 坚守一个稳定支持版本
这两种各有利弊,但并不妨碍挪窝的考虑,2017 年 9 月,Java 平台的主架构师 Mark Reinhold 提议,要求将 Java 的更新周期从之前的每 2 年一次调整到每 6 个月一次,三年发布一个LTS版本(Long term support,长期支持版本),也有人建议两年发布一个LTS(从17开始Java每两年也就是4个版本一个LTS,也就是下一个LTS是Java 21)。
Java 8 对于目前依然是主流
Snk在2021年6月发布的不同报告,显示11是最流行的版本
New Relic也发布了不同版本分布图
回到一开始的问题,我们应该使用哪个一个Java版本?没有唯一答案
为什么升级?
如果升级,那为什么要从现有稳定的区域升级到未涉足区域?有如下几个点
1.生态支持新的版本 更多的库和中间件开始支持稳定新版本,如Spring Boot 3、Spring 6需要ava 17,Kafka 4将会舍去Java 8的支持
2.高性价比的降本增效 高的版本会带来性能改进,可能很小,但是在某一个情况可能只有百分比、千分比或者什么都没有,但是随着时间的推移,将会获得免费的性能,如从服务器几百万的费用中抽取一个百分比,就能获取免费的性能,何乐而不为
3.人才的吸引和维护 可以吸引更多优秀的人才,因为新的东西总会更让人感兴趣,减少JVM后端和安全修复的成本,更低的延迟和运维要求。对于容易的大小,只需要调整 -Xmx和 -Xms,更快的OOM
如何升级到Java 11
主要先升级maven-compiler-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
为什么不升级到其他版本 Java9?Java10?,展望未来java17,但是Java 11的时候,Oracle JDK发布了一个许可限制,首先我们不能在没有生产许可的情况下构建自己的镜像,这意味着要和oracle签订许可合同,这时候Open JDK是一个不错的选择,但是Java 17发生改变了,如果软件可以免费重发布,就可以免费使用17,是否使用可以联系律师。升级可以先从非核心微服务开始,经过 编译 - 测试 - 允许 一直到核心服务的升级路线,中间一定需要更多的测试用例来配合,一般有两种方式升级
- A.用JAVA11编译,在JAVA11运行
- B.用JAVA8编译,在JAVA11运行
升级路线
- 今天:8 -> 11 ( -> 16 ) -> 17
- 快速:11 -> 17
Scala支持的兼容性表,但是不支持模块化,可以参考[ 3 ]
Kotlin
JDK 9-12 最小支持版本 1.3.30
JDK17 最小支持版本 1.6.0
构建工具
工具:Jdpes
插件:maven: maven-jdeps-plugin
描述:在jdk bin目录下,显示模块依赖,如内部API的使用,如果你想为管理人员准备一份关于估计工作量的报告,这个工具是个不错的选择
工具:Jdeprscan
插件:maven: maven-jdeprscan-plugin
描述:会扫描无效@Deprecated的api哪些被使用
工具:Maven Plugin Version
插件:maven:versions-maven-plugin
描述:
- display-plugin-updates 可以显示你的版本中哪些插件可以升级
- display-dependency-updates 可以显示哪些依赖已经可以更新哪些内容
虚拟机配置
java
-verbose:gc
-Xloggc:my_very_own_gc-%t.log
-XX:+PrintGC
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCCause
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-XX:+PrintReferenceGC-
XX:+PrintTenuringDistribution
变成
java
-Xlog:gc*,gc+ref=debug.gc+phases=debug.gc+age=debug,safepoint:file=gc.log
-jar jar.binks
多个参数记不住,使用工具,详情见 参考[5] ,命令分析参考[4]
升级注意
* 8 - 11 jdk允许的时间精确度改变了,发生什么呢
底层操作系统显示时间,会得到6位数(毫秒),而不是3位数(毫秒),如果对于精确度有业务影响,建议制作自己的时钟,提供需要的精确度,只需要用容器内存大小的百分比来表示堆大小就可以了
* JDK11 默认使用G1 GC,fullGc是多线程的
* ‘_’这个也是关键字了,__双下划线满足需要
* var特性提高可读性
* 升级过程中,一些容器开始不断被杀死
原因:java11进程的RSS比类似配置的java 8进程的RSS高
参考
[ 1 ] JVM Ecosystem Report
[ 2 ] The State of Java
[ 3 ] JDK Compatibility | Scala Documentation