一文搞定jdk8升级到jdk11

news2024/11/17 14:27:21

一、背景

为什么要升级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下载

这里不过多阐述,需要注意区分JDK的arm版本与x64版本。

  • IDEA选择JDK11启动

图片

  • 框架升级 

修改pom文件

<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<java.version>11</java.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
<lombok.version>1.18.12</lombok.version>

软件

最低版本

spring-boot

2.1.x 开始支持jdk11

spring

5.1.x

idea

2018.2

maven

3.5.0

lombok

1.18.x

netty

需要升级到 4.1.33.Final 或之后的版本,否则会引起堆外内存增长

apache common lang3

3.12.0

jdk11已移除,需手工依赖二方库

<dependency>
    <groupId>javax.xml.soap</groupId>
    <artifactId>javax.xml.soap-api</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>2.3.3</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>com.sun.activation</groupId>
    <artifactId>javax.activation</artifactId>
    <version>1.2.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba.jvm</groupId>
    <artifactId>java-migration-jdk-patch</artifactId>
    <version>0.3.1</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
</dependency>
  • 遇到的问题

Deprecated: A global security auto-configuration is now provided

图片

在Spring Boot 2.0及以上版本中,这个配置项已经被废弃并移除。如果你要关闭端点的安全性,需要在Spring Security的配置中对Actuator端点进行配置。该配置项是默认开启安全检测。

Dependency 'org.hibernate:hibernate-validator:' not found 

图片

需要指定版本号

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.4.Final</version>
</dependency>

应用不能进行远程调试

原因分析

JDK 8 中 jdwp 默认绑定的 host/ip 是 0.0.0.0,初于安全考虑在 JDK 9 后改成了 localhost(127.0.0.1),导出如果开发者在配置调试选项时只指定端口时,在升级后无法进行远程调试。

解决方案

指定调试选项时设置 host/ip 为 *,如:

agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000

或者 0.0.0.0,如:

agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000

其他问题

1、maven-compiler-plugin:此插件建议直接升级到最新版,同时在父Pom和每个你需要额外确定版本的包(比如说打给别人用的JDK8版本的包)里的Pom,指定版本:

​<maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target>

2、Springboot和Spring版本:Spring从5.1开始支持11,Springboot从2.1.X开始支持11,我们的推荐是支持升级到当前的最新版;

3、Netty因为堆外内存的释放问题,请升级到4.1.33以上的版本;

4、lombok因为会在编译期插入自己的编译逻辑,所以升级到11之后,需要将lombok升级到最新版,(编辑文档时的最新版本是1.18.24);

5、可能大部分应用都需要进行Spring或者Springboot升级,请务必做好回归;

6、security-spring-boot-starter分为1.x.x和2.x.x版本,对应springboot1和springboot2,请升级到2.x.x版本;

应用部署发布

  • 使用G1垃圾回收器
去除
#SERVICE_OPTS="${SERVICE_OPTS} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSMaxAbortablePrecleanTime=5000"
#SERVICE_OPTS="${SERVICE_OPTS} -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFractinotallow=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:G1HeapReginotallow=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团队)

通常G1 GC是一个免调参的GC,并不需要额外的参数调整。老的一些的八股文Java GC调参经验并不适用。

-Xmn参数一般不需要设置

G1预设了-XX:NewSize和-XX:MaxNewSize的值(不一致),会根据实际运行来计算设置每次GC的young区的size,实现GC暂停的软可控。

-XX:NewRatio同理不需要设置
-XX:SurvivorRatio一般也不设置

通常绝大部分使用者并不清楚这个参数的含义以及对GC带来的影响,G1会自适应处理这个参数相关的GC行为。

升级G1后可能需要关注的参数​
-XX:MaxGCPauseMillis=N,G1暂停的目标时间(毫秒)

默认为200,很多用户会刻意设小,通常情况下意义不大。G1实际的GC暂停任务,并不会随着暂停时间缩小而变少,可以设小会导致更频繁的GC影响吞吐。一般不需要设置,如果需要更好的吞吐,通常是设置更大,保持young区不会缩减的太小。也可以咨询JVM答疑专家考虑调整-XX:NewSize和-XX:MaxNewSize,来保持young 区的Size,维持合适的吞吐性能。

-XX:InitiatingHeapOccupancyPercent=N -XX:-G1UseAdaptiveIHOP (电商核心使用)

这两个参数通常同时使用。JDK11引入了G1UseAdaptiveIHOP来提升老区的利用率(大堆,通常大几十G,或者100G以上)。在我们容器规格中等规模的heap(通常5-20g)的size中,有时会出现old gc过于频繁或者young gc过于频繁的现象。因此考虑一个合适的静态IHOP(老区使用占全堆比例触发GC的阈值),会更加合适。

-XX:G1HeapRegionSize,(电商核心通常使用8m-32m)

设置G1 region的大小,应对humongous对象(超过heap region size一半独占一个或多个region)引起的GC异常。Heap region size默认为Heap size/2048,如果默认值过小,humongous对象分配过多,容易引起To-space exhausted的异常暂停时间:

[2024-01-05T14:14:31.817+0800] GC(266) To-space exhausted

-XX:G1HeapWastePercent,(默认5,部分电商核心应用设置为2)​

G1在回收老区对象时,可以允许5% heap size的垃圾对象不回收,来减少mixed GC的暂停开销。当Xmx10G时,5%就有500m的空间,对于Java heap是一种浪费,因此可以考虑减少heap空间浪费设置成2。不建议设置成0,可能会极大增加mixed GC的暂停。

-XX:G1MixedGCCountTarget,Mixed GC目标次数,默认为8​

实际的Mixed GC次数通常会小于G1MixedGCCountTarget,如果Concurrent mark/mixed gc的周期并不频繁,单次mixed gc的暂停过长,通常可以考虑增大这个参数,例如16,来分散单次mixed GC暂停的工作量,减少暂停时间。

升级G1的常见问题​
CMS升级G1后,容器和Java进程内存占用变高​

很多应用在升级JDK11,出现容器和Java进程内存整体变高的现象,主要源自Heap的使用率差异。CMS的Old generation为非移动式,由 CMSInitiatingOccupancyFraction 来控制使用比例来触发gc,因此应用启动后短时间内,heap old区使用率不会上升。而G1的heap region是松散管理,整体利用heap,所以显得内存使用率高。本质是一个heap利用率的问题,cms初始留着部分heap不用。这个问题可以通过调低Xmx来解决(部分电商核心使用这个方案)。

GC日志中To-space exhausted引起的异常暂停​

绝大部分是由于大对象分配过多,GC日志中频繁出现

Pause Young (Concurrent Start) (G1 Humongous Allocation)

大对象分配过多,会导致堆空间快速被占满,GC是出现To-space exhausted/evacuation failure,需要额外的暂停时间处理,甚至出现更耗时的Full GC全堆整理。

GC过于频繁​

相比传统的CMS/Parallel GC,固定的young 区size。G1的young区size是自动调整的,当为了满足暂停要求时,会缩小young区,导致GC频率过高。一般的情况是避免MaxGCPauseMillis设置过小,参考上面参数的介绍。或者增大MaxGCPauseMillis的配置,同时有必要的话咨询答疑专家,调整-XX:NewSize和-XX:MaxNewSize。

Mixed GC暂停过长​

G1除了整理清除young区对象的young GC,还有在Concurrent mark之后,包含整理老区对象的mixed gc。因此通常mixed GC会有更长的暂停时间。如果单次mixed GC暂停过长,考虑增大上面介绍的参数G1MixedGCCountTarget,来进一步分散老区对象整理的任务,降低暂停

四、升级效果

日常运行

图片

可以看到在日常运行中,G1的垃圾回收耗时也有不错的提升

压测效果

相同压测条件下TPS20

图片

图片

可以明显看到GC耗时降低了不少,速度快了70%左右

图片

线上运行情况

图片

从图中可以看到YGC的耗时明显缩短,性能将近提升50%!这归功于分代收集的能力

YGC平均暂停时间

YGC次数

效果

JDK8+CMS

7.4ms

10347

JDK11+G1

3.74ms

10649

性能提升49.5%

五、JDK11新玩法

字符串String加强

String str = " i am lzc ";
boolean isblank = str.isBlank();         //判断字符串是空白
boolean isempty = str.isEmpty();         //判断字符串是否为空
String  result1 = str.strip();           //首位空白
String  result2 = str.stripTrailing();  //去除尾部空白
String  result3 = str.stripLeading();   //去除首部空白
String  copyStr = str.repeat(2);        //复制几遍字符串
long  lineCount = str.lines().count();  //行数统计


System.out.println(isblank);            //结果:false            
System.out.println(isempty);            //结果:false 
System.out.println(result1);            //结果:i am lzc 
System.out.println(result2);            //结果: i am lzc 
System.out.println(result3);            //结果:i am lzc  
System.out.println(copyStr);            //结果: i am lzc  i am lzc  
System.out.println(lineCount);          //结果:1

文件Files方法加强

Path filePath = Files.writeString(Path.of("/temp/a.txt"), "Sample text");
String fileContent = Files.readString(filePath);
System.out.println(fileContent.equals("Sample text"));

数据流Stream方法加强

//Stream,允许接受一个null值,计算count时,返回0
long count = Stream.ofNullable(null).count();
System.out.println(count); // 0




//方法都接受一个谓词来决定从流中放弃哪些元素
//通俗理解:从集合中删除满足条件的元素,直到不满足为止
List list1 = Stream.of(1, 2, 3, 2, 1)
        .dropWhile(n -> n < 3)
        .collect(Collectors.toList());
System.out.println(list1); // [3, 2, 1]


//方法都接受一个谓词来决定从流中选用哪些元素
//通俗理解:从集合中提取满足条件的元素,直到不满足为止
List list2 = Stream.of(1, 2, 3, 2, 1)
        .takeWhile(n -> n < 3)
        .collect(Collectors.toList());
System.out.println(list2); // [1, 2]

集合List、Map等方法加强

List list1 = List.of(1, 3, 5, 7);
List list2 = List.copyOf(list1);
System.out.println(list2); //结果: [1,3,5,7]


Map<Integer, String> map1 = Map.of(1, "a", 2, "b", 3, "c");
Map<Integer, String> map2 = Map.copyOf(map1);
System.out.println(map2); //结果: {1=a, 2=b, 3=c}

optional加强

//新增orElseThrow,为空时抛异常
Object v2 = Optional.ofNullable(null).orElseThrow();      //结果:抛异常


//新增ifPresentOrElse,不为null执行第1个回调函数,为null时执行第2个回调函数
Optional.ofNullable(null).ifPresentOrElse(
        (x) -> {
            System.out.println("数据:" + x);
        }, () -> {
            System.out.println("数据不存在");
        });


//提供另一个Optionals 作为空Optionals的回调
Object v3 = Optional.ofNullable(null)
        .or(() -> Optional.of("fallback"))
        .get();   //结果:fallback
System.out.println(v3);

HTTP Client

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(uri))
    .build();
// 异步
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println)
    .join();


// 同步
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1706803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python开发 —— 对象type、object、class

1. "Python中一切皆为对象"的理解 在Python中&#xff0c;一切皆为对象的意思是指&#xff1a;无论是数字、字符串、函数、类、模块等任何数据类型&#xff0c;都可以被看做是一个对象。每个对象都具有自己的属性和方法&#xff0c;可以被操作和调用。 例如&#xff…

IP地址SSL证书应用场景以及如何申请?

一&#xff1a;IP地址SSL证书主要应用于以下几种场景&#xff1a; 1.API接口保护&#xff1a;许多云服务和企业内部系统使用IP地址直接作为服务的访问点&#xff0c;特别是在API接口的调用中。IP地址SSL证书可以为这些API接口提供必要的安全加密&#xff0c;确保数据在传输过程…

DreamPose: Fashion Image-to-Video Synthesis via Stable Diffusion

UW&UCB&Google&NVIDIA ICCV23https://github.com/johannakarras/DreamPose?tabreadme-ov-file 问题引入 输入参考图片 x 0 x_0 x0​和pose序列 { p 1 , ⋯ , p N } \{p_1,\cdots,p_N\} {p1​,⋯,pN​}&#xff0c;输出对应视频 { x 1 ′ , ⋯ , x N ′ } \{x_1,…

停车场变综合楼,结构分析助力低碳设计

PLAXIS 和 RAM 助力确定更有效的结构设计并大幅降低施工成本 总部和周边区域 桑坦德银行位于英国的新总部将现有的四个英国办事处合并到米尔顿凯恩斯的一个中心枢纽&#xff0c;位于伦敦以北 50 英里。 Unity Place 将作为桑坦德银行约 5,000 名员工的办公场所。该项目总投资 …

AIGC笔记--基于PEFT库使用LoRA

1--相关讲解 LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS LoRA 在 Stable Diffusion 中的三种应用&#xff1a;原理讲解与代码示例 PEFT-LoRA 2--基本原理 固定原始层&#xff0c;通过添加和训练两个低秩矩阵&#xff0c;达到微调模型的效果&#xff1b; 3--简单代…

web自动化-下拉框操作/键鼠操作/文件上传

在我们做UI自动化测试的时候&#xff0c;会有一些元素需要特殊操作&#xff0c;比如下拉框操作/键鼠操作/文件上传。 下拉框操作 在我们很多页面里有下拉框的选择&#xff0c;这种元素怎么定位呢&#xff1f;下拉框分为两种类型&#xff1a;我们分别针对这两种元素进行定位和…

答应我!养猫就一定要入手的七款好物!养猫真的会开心

养猫是一件让人愉悦的事情&#xff0c;猫咪的陪伴能让我们感到温暖和满足。然而&#xff0c;想要让猫咪健康快乐地成长&#xff0c;除了关心它们的饮食和健康&#xff0c;还需要为它们准备一些必要的生活用品。今天&#xff0c;我将为大家推荐几个养猫必备的好物&#xff0c;让…

黑马头条day6总结

1、wemedian错误 一开始没加EnableFeignClients(basePackages "com.heima.apis")导致获取ischeduleClient错误&#xff0c;找不到bean。 我看教程的代码中没有&#xff0c;【ComponentScan({"com.heima.apis","com.heima.wemedia"})】&#x…

11款必备IP地址管理软件,你都用过吗?

1、LightMesh IPAM 产品描述&#xff1a;LightMesh IPAM 是一款功能强大的工具&#xff0c;可简化和自动化互联网协议网络的管理。它提供可扩展性、子网规划器、即时云发现、IP 和网络管理以及 IP 规划和可视化&#xff0c;以帮助您优化效率、可见性和安全性。 特征&#xff1…

强化学习——学习笔记

一、什么是强化学习&#xff1f; 强化学习 (Reinforcement Learning, RL) 是一种通过与环境交互来学习决策策略的机器学习方法。它的核心思想是让智能体 (Agent) 在执行动作 (Action)、观察环境 (Environment) 反馈的状态 (State) 和奖励 (Reward) 的过程中&#xff0c;学习到…

C++音视频开发面试题集锦

老规矩&#xff0c;先上面试题目&#xff1a; 1、iOS 中系统 API 提供了哪些视频编码的方式&#xff1f;2、VideoToolbox 视频帧解码失败以后应该如何重试&#xff1f;3、如何使用 PSNR 对视频转码质量进行评估&#xff1f;4、什么是 VAO&#xff0c;什么是 VBO&#xff0c;它…

【图书推荐】《机器学习实战(视频教学版)》

本书用处 快速入门Python机器学习基础算法。 最后3个综合实战项目&#xff08;包括新闻内容分类实战、泰坦尼克号获救预测实战、中药数据分析项目实战&#xff09;可以作为研究可以的素材。 内容简介 本书基于Python语言详细讲解机器学习算法及其应用&#xff0c;用于读者快…

Java 五种内部类演示及底层原理详解

内部类 什么是内部类 在A类的内部定义B类&#xff0c;B类就被称为内部类 发动机类单独存在没有意义 发动机为独立个体 可以在外部其他类里创建内部类的对象去调用方法 类的五大成员 属性 方法 构造方法 代码块 内部类 内部类的访问特点 内部类可以直接访问外部类的成员&a…

Java处理CSV文件示例

Java处理CSV文件示例 1. 导入依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-csv</artifactId><version>1.10.0</version></dependency>文件示例 下面是示例文件文件数据 vscode和idea都有解析…

第二证券股市资讯:连续3天20%涨停!A股这一赛道,牛股批量出现!

今日&#xff0c;A股小幅轰动调整&#xff0c;上证指数下试3100点支撑。 两市成交7453亿元&#xff0c;创近4个月来新低&#xff0c;超4000只个股下跌。盘面上&#xff0c;电力、芯片、煤炭、石油等板块涨幅居前&#xff0c;铜缆高速衔接、房地产、工程机械、网络游戏等板块跌幅…

word-主控文档、文档拆分及标书编写技巧建议

一、主控文档 视图-大纲视图-显示文档-插入子文档 子文档一旦更新&#xff0c;主文档也会更新。更新主文档&#xff0c;子文档也会更新 需要注意&#xff0c;不可修改子文档名字 二、上交文件 显示文档-折叠子文档-只显示一级-取消链接-关闭大纲视图-保存 三、文档拆分 根…

Transformer 从attention到grouped query attention (GQA)

Attention原理和理解 attention原理参考&#xff1a; Attention Is All You Need The Illustrated Transformer – Jay Alammar – Visualizing machine learning one concept at a time. Transformer图解 - 李理的博客 Attention首先对输入x张量乘以WQ, WK, WV得到query,…

本地开发正常 线上CI/CD构建项目过程报错文件未能正确引用

问题快照 原因分析&#xff1a; 一般遇到这样的错误就是 文件路径或者文件名称未能正确匹配 或者文件不存在 会报这样的错误 以为很好解决 但这次 都排查 了 就是 没发现原因 不管怎么说还是要感谢 GPT的能力(分析问题的能力) 先上图 当我看到 第四步的时候 我立马 去仓库里查…

没开玩笑!高速信号不能参考电源网络这条规则,其实很难做到

高速先生成员--黄刚 看到这篇文章的题目&#xff0c;我相信大家心里都呈现出了这么一个场景&#xff1a;高速信号线在L20层&#xff0c;我只要把L19和L21层都铺上完整的地平面&#xff0c;这不就满足了高速信号线不能参考电源平面这条规则了吗&#xff1f;这难道很难做到吗&…

Windows 使用技巧

Windows 使用技巧 ①局域网内共享文件 ②CTRL Y 和 CTRL Z ①局域网内共享文件 第一步&#xff1a; 选择要共享的文件&#xff08;分享方操作&#xff09; 第二步&#xff1a; 右键打开属性&#xff0c;选择共享&#xff08;分享方操作&#xff09; 第三步&#xff1a; …