首页 > 应用开发 > IT综合 > JDK11升级JDK17最全实践干货来了
来源:京东云开发者
2021年9月14日,Oracle发布了可以长期支持的JDK17版本,那么从JDK11到JDK17,到底带来了哪些特性呢?亚毫秒级的ZGC效果到底怎么样呢?值得我们升级吗?而且升级过程会遇到哪些问题呢?带着这些问题,本篇文章将带来完整的JDK11升级JDK17最全实践。
1)长期支持版本
JDK17是Oracle官方在2021年9月14日发布的一个长期支持(LTS)版本,意味着它将获得长期的更新和支持,有助于保持程序的稳定性和可靠性。
2)性能提升
更好的垃圾回收器。综合评估,从Java 8 升级到 Java 11,G1GC平均速度提升16.1%,ParallelGC为4.5%,从Java 11 升级到 Java 17,G1GC平均速度提升8.66%,ParallelGC为6.54%(基于OptaPlanner的用例基准测试表明:https://www.optaplanner.org/blog/2021/09/15/HowMuchFasterIsJava17.html)
最大的亮点是带来了稳定版的ZGC垃圾回收器,达到亚毫秒级停顿。
3)新语法和特性
Switch表达式简化、Text Blocks文本块、instanceof 的模式匹配升级和NullPointerException提示信息改进等
4)支持最新的技术和框架
Spring framework6 和Spring Boot3 都默认使用 Java 17作为最低版本
先给出结论:
JDK17相对于JDK8和JDK11,所有垃圾回收器的性能都有很明显的提升,特别是稳定版的ZGC垃圾回收器
不论任何机器配置下,都推荐使用ZGC,ZGC的停顿时间达到亚毫秒级,吞吐量也比较高
我在JDOS平台上选择了不同配置的机器(2C4G、4C8G、8C16G),并分别使用JDK8、JDK11和JDK17进行部署和压测。
整个压测过程限时60分钟,用180个虚拟用户并发请求一个接口,每次接口请求都创建512Kb的数据。最终产出不同GC回收器的各项指标数据,来分析GC的性能提升效果。
以下是压测的性能情况:

2021年9月,Oracle宣布JDK17可以免费商用,直到下一个 LTS 版本之后继续提供整整一年,同时Oracle 将继续按照自 Java 9 以来的相同版本和时间表提供GPL下的Oracle OpenJDK 版本。
2023年9月,OracleJDK发布了新的LTS版本 JDK21,这就意味着从2024年9月开始,在生产环境使用 OracleJDK17 将需要付费。

参考:https://www.oracle.com/hk/java/technologies/downloads/#java17
OracleJDK和OpenJDK这两个之间没有真正的技术差别,因为针对Oracle JDK构建过程是基于OpenJDK的。自从JDK11开始,OracleJDK和OpenJDK在功能上基本相同,所以推荐使用 OpenJDK17 或其他开源的JDK版本,这些开源版本都是基于OpenJDK构建并提供长期支持的,比如:AdoptOpenJDK、RedHatOpenJDK。

官方参考:https://blogs.oracle.com/java/post/oracle-jdk-releases-for-java-11-and-later
ZGC垃圾回收器从实验性功能更改为正式产品功能,从JDK11引入以来,经过持续的迭代升级,目前已经足够稳定。需要手动开启,开启方式:-XX:+UseZGC
G1垃圾回收器仍然作为默认垃圾回收器,进行改进升级,主要包括可中止的混合收集集合、NUMA 可识别内存分配等
JDK14开始删除 CMS 垃圾回收器
JDK14开始弃用 ParallelScavenge 和 SerialOld GC 的组合使用
JDK15禁用偏向锁,默认禁用:-XX:+UseBiasedLocking
NullPointerException 提示信息改进
JDK14以前的出现NullPointerException时,只能定位到所在异常行,无法定位具体是哪个变量。改进后的NullPointerException,可以清晰描述具体变量,提升了空指针异常的可读性。

5.2、新语法特性
switch表达式带来了简化式的编码方式,提供了新的分支切换方式,即 -> 符号,右则表达式方法体在执行完分支方法之后,自动结束 switch 分支,同时 -> 右则方法块中可以是表达式、代码块或者是手动抛出的异常
参考:https://openjdk.org/jeps/361
传统写法

新写法

5.2.2、Text Blocks文本块
参考:https://openjdk.org/jeps/378
通过编写 """,来减少转义字符和换行符,达到简化代码和提高代码可读性的目的

5.2.3、Record类型
参考:https://openjdk.org/jeps/395
record 是 JDK 14 引入的关键字,用于声明不可变的数据类。它适用于存储纯粹的值类型数据,如接口传输数据、坐标点和只读的日志记录。与 lombok 相比,record 简化了定义纯粹数据类型的过程。由于 record 类是不可变的,成员变量只能设置一次且无法更改,无需提供显式的 setter() 方法。
1、定义Point类,使用关键字record,未定义get/set

2、查看编译后的字节码文件


3、使用Point类

5.2.4、instanceof 的模式匹配升级
instanceof类型判断再也不需要强制转换


<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target></properties>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.15</version></parent>
<properties><!-- 框架版本配置--><springboot-version>2.7.15</springboot-version><springframework.version>5.3.29</springframework.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>${springboot-version}</version><scope>import</scope><type>pom</type></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-framework-bom</artifactId><version>${springframework.version}</version><scope>import</scope><type>pom</type></dependency></dependencies></dependencyManagement>

#放开循环依赖spring.main.allow-circular-references=true
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version></dependency>

Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null
/*** 增加如下配置可解决Spring Boot 2.7.15 与Swagger 3.0.0 不兼容问题**/public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {return new BeanPostProcessor() {public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {customizeSpringfoxHandlerMappings(getHandlerMappings(bean));}return bean;}private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null).collect(Collectors.toList());mappings.clear();mappings.addAll(copy);}("unchecked")private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {try {Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");field.setAccessible(true);return (List<RequestMappingInfoHandlerMapping>) field.get(bean);} catch (IllegalArgumentException | IllegalAccessException e) {throw new IllegalStateException(e);}}};}
<!-- API, java.xml.bind module --> <dependency> <groupId>jakarta.xml.bind</groupId> <artifactId>jakarta.xml.bind-api</artifactId> <version>2.3.2</version></dependency> <!-- Runtime, com.sun.xml.bind module --><dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.2</version></dependency>
Unable to make field private static final java.lang.reflect.Method jdk.proxy2.$Proxy97.m0 accessible: module jdk.proxy2 does not "opens jdk.proxy2" to unnamed module @61d47554



--add-opens java.management/java.lang.management=ALL-UNNAMED --add-opens jdk.management/com.sun.management.internal=ALL-UNNAMED --add-opens java.management/sun.management=ALL-UNNAMED
--add-opens java.base/java.time=ALL-UNNAMED
--add-opens java.base/java.util.concurrent=ALL-UNNAMED--add-opens java.base/java.util.concurrent.locks=ALL-UNNAMED--add-opens java.base/java.security=ALL-UNNAMED--add-opens java.base/jdk.internal.loader=ALL-UNNAMED--add-opens java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED
--add-exports java.base/sun.security.action=ALL-UNNAMED--add-opens java.base/java.lang=ALL-UNNAMED--add-opens java.base/java.math=ALL-UNNAMED--add-opens java.base/java.util=ALL-UNNAMED--add-opens java.base/sun.util.calendar=ALL-UNNAMED
-end-
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70024924/viewspace-2995592/ ,如需转载,请注明出处,否则将追究法律责任。