亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

jdk8升級到j(luò)dk11如何升級的真實案例(親身經(jīng)歷)

 更新時間:2025年10月03日 16:45:37   作者:程序員小2  
JDK11升級因G1GC性能提升及Spring?Boot?2.7+不再支持Java?8,需調(diào)整依賴和GC參數(shù),帶來內(nèi)存優(yōu)化和性能提升(如TPS增70%),并增強String、Files、Stream等API及新HTTP?Client

一、背景

為什么要升級JDK11

性能

  • JDK11的G1的GC性能高很多,對比JDK8無論是性能還是內(nèi)存占比都有很大的提升,業(yè)內(nèi)各項數(shù)據(jù)指標(biāo)也都表明JDK11的G1在應(yīng)對突發(fā)流量的下的效果驚人;

一文搞定jdk8升級到j(luò)dk11_System

  • 版本兼容
  • Spring Boot 2.7.x及以后的版本將不再支持Java 8作為最低版本。Spring Boot 2.6.x是最后一個正式支持Java 8的主線版本,一些新的中間件與組件也不再支持JDK8了;
  • 必然趨勢
  • JDK11(LTS)已經(jīng)成為業(yè)界主流,在Java開發(fā)社區(qū)和工業(yè)界中得到了廣泛的接受和使用;

一文搞定jdk8升級到j(luò)dk11_System_02

二、升級前你要知道的點

  • JDK11版本改動較大,且不會向下兼容。所以當(dāng)你的業(yè)務(wù)代碼越復(fù)雜,調(diào)用的鏈路越多,升級的難度越大。你會遇到很多兼容性問題,比如  二方包不支持新版本JDK;
  • JDK11移除了部分在Java 8就已經(jīng)標(biāo)記為過時的API例如sun.misc.Unsafe的部分方法,所以你的升級可能還涉及到代碼的改動;
  • 驗證是個漫長而又耗時的過程,很多問題可能在運行時階段才會暴露,你需要驗證系統(tǒng)整體功能來保證系統(tǒng)穩(wěn)定;

三、升級過程

本地升級,讓你的JDK11跑起來

  • 本地JDK11下載

這里不過多闡述,需要注意區(qū)分JDK的arm版本與x64版本。

  • IDEA選擇JDK11啟動

一文搞定jdk8升級到j(luò)dk11_java_03

  • 框架升級 

修改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 或之后的版本,否則會引起堆外內(nèi)存增長

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></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

一文搞定jdk8升級到j(luò)dk11_G1_04

在Spring Boot 2.0及以上版本中,這個配置項已經(jīng)被廢棄并移除。如果你要關(guān)閉端點的安全性,需要在Spring Security的配置中對Actuator端點進行配置。該配置項是默認(rèn)開啟安全檢測。

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

一文搞定jdk8升級到j(luò)dk11_System_05

需要指定版本號

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

應(yīng)用不能進行遠(yuǎn)程調(diào)試

原因分析

JDK 8 中 jdwp 默認(rèn)綁定的 host/ip 是 0.0.0.0,初于安全考慮在 JDK 9 后改成了 localhost(127.0.0.1),導(dǎo)出如果開發(fā)者在配置調(diào)試選項時只指定端口時,在升級后無法進行遠(yuǎn)程調(diào)試。

解決方案

指定調(diào)試選項時設(shè)置 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,我們的推薦是支持升級到當(dāng)前的最新版;

3、Netty因為堆外內(nèi)存的釋放問題,請升級到4.1.33以上的版本;

4、lombok因為會在編譯期插入自己的編譯邏輯,所以升級到11之后,需要將lombok升級到最新版,(編輯文檔時的最新版本是1.18.24);

5、可能大部分應(yīng)用都需要進行Spring或者Springboot升級,請務(wù)必做好回歸;

6、security-spring-boot-starter分為1.x.x和2.x.x版本,對應(yīng)springboot1和springboot2,請升級到2.x.x版本;

應(yīng)用部署發(fā)布

  • 使用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調(diào)優(yōu)的注意事項(數(shù)據(jù)來源JVM團隊)

通常G1 GC是一個免調(diào)參的GC,并不需要額外的參數(shù)調(diào)整。老的一些的八股文Java GC調(diào)參經(jīng)驗并不適用。

-Xmn參數(shù)一般不需要設(shè)置

G1預(yù)設(shè)了-XX:NewSize和-XX:MaxNewSize的值(不一致),會根據(jù)實際運行來計算設(shè)置每次GC的young區(qū)的size,實現(xiàn)GC暫停的軟可控。

-XX:NewRatio同理不需要設(shè)置

-XX:SurvivorRatio一般也不設(shè)置

通常絕大部分使用者并不清楚這個參數(shù)的含義以及對GC帶來的影響,G1會自適應(yīng)處理這個參數(shù)相關(guān)的GC行為。

升級G1后可能需要關(guān)注的參數(shù)

-XX:MaxGCPauseMillis=N,G1暫停的目標(biāo)時間(毫秒)

默認(rèn)為200,很多用戶會刻意設(shè)小,通常情況下意義不大。G1實際的GC暫停任務(wù),并不會隨著暫停時間縮小而變少,可以設(shè)小會導(dǎo)致更頻繁的GC影響吞吐。一般不需要設(shè)置,如果需要更好的吞吐,通常是設(shè)置更大,保持young區(qū)不會縮減的太小。也可以咨詢JVM答疑專家考慮調(diào)整-XX:NewSize和-XX:MaxNewSize,來保持young 區(qū)的Size,維持合適的吞吐性能。

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

這兩個參數(shù)通常同時使用。JDK11引入了G1UseAdaptiveIHOP來提升老區(qū)的利用率(大堆,通常大幾十G,或者100G以上)。在我們?nèi)萜饕?guī)格中等規(guī)模的heap(通常5-20g)的size中,有時會出現(xiàn)old gc過于頻繁或者young gc過于頻繁的現(xiàn)象。因此考慮一個合適的靜態(tài)IHOP(老區(qū)使用占全堆比例觸發(fā)GC的閾值),會更加合適。

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

設(shè)置G1 region的大小,應(yīng)對humongous對象(超過heap region size一半獨占一個或多個region)引起的GC異常。Heap region size默認(rèn)為Heap size/2048,如果默認(rèn)值過小,humongous對象分配過多,容易引起To-space exhausted的異常暫停時間:

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

-XX:G1HeapWastePercent,(默認(rèn)5,部分電商核心應(yīng)用設(shè)置為2)

G1在回收老區(qū)對象時,可以允許5% heap size的垃圾對象不回收,來減少mixed GC的暫停開銷。當(dāng)Xmx10G時,5%就有500m的空間,對于Java heap是一種浪費,因此可以考慮減少heap空間浪費設(shè)置成2。不建議設(shè)置成0,可能會極大增加mixed GC的暫停。

-XX:G1MixedGCCountTarget,Mixed GC目標(biāo)次數(shù),默認(rèn)為8

實際的Mixed GC次數(shù)通常會小于G1MixedGCCountTarget,如果Concurrent mark/mixed gc的周期并不頻繁,單次mixed gc的暫停過長,通常可以考慮增大這個參數(shù),例如16,來分散單次mixed GC暫停的工作量,減少暫停時間。

升級G1的常見問題

CMS升級G1后,容器和Java進程內(nèi)存占用變高

很多應(yīng)用在升級JDK11,出現(xiàn)容器和Java進程內(nèi)存整體變高的現(xiàn)象,主要源自Heap的使用率差異。CMS的Old generation為非移動式,由 CMSInitiatingOccupancyFraction 來控制使用比例來觸發(fā)gc,因此應(yīng)用啟動后短時間內(nèi),heap old區(qū)使用率不會上升。而G1的heap region是松散管理,整體利用heap,所以顯得內(nèi)存使用率高。本質(zhì)是一個heap利用率的問題,cms初始留著部分heap不用。這個問題可以通過調(diào)低Xmx來解決(部分電商核心使用這個方案)。

GC日志中To-space exhausted引起的異常暫停

絕大部分是由于大對象分配過多,GC日志中頻繁出現(xiàn)

Pause Young (Concurrent Start) (G1 Humongous Allocation)

大對象分配過多,會導(dǎo)致堆空間快速被占滿,GC是出現(xiàn)To-space exhausted/evacuation failure,需要額外的暫停時間處理,甚至出現(xiàn)更耗時的Full GC全堆整理。

GC過于頻繁

相比傳統(tǒng)的CMS/Parallel GC,固定的young 區(qū)size。G1的young區(qū)size是自動調(diào)整的,當(dāng)為了滿足暫停要求時,會縮小young區(qū),導(dǎo)致GC頻率過高。一般的情況是避免MaxGCPauseMillis設(shè)置過小,參考上面參數(shù)的介紹?;蛘咴龃驧axGCPauseMillis的配置,同時有必要的話咨詢答疑專家,調(diào)整-XX:NewSize和-XX:MaxNewSize。

Mixed GC暫停過長

G1除了整理清除young區(qū)對象的young GC,還有在Concurrent mark之后,包含整理老區(qū)對象的mixed gc。因此通常mixed GC會有更長的暫停時間。如果單次mixed GC暫停過長,考慮增大上面介紹的參數(shù)G1MixedGCCountTarget,來進一步分散老區(qū)對象整理的任務(wù),降低暫停

四、升級效果

日常運行

一文搞定jdk8升級到j(luò)dk11_G1_06

可以看到在日常運行中,G1的垃圾回收耗時也有不錯的提升

壓測效果

相同壓測條件下TPS20

一文搞定jdk8升級到j(luò)dk11_System_07

一文搞定jdk8升級到j(luò)dk11_G1_08

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

一文搞定jdk8升級到j(luò)dk11_G1_09

線上運行情況

一文搞定jdk8升級到j(luò)dk11_System_10

從圖中可以看到Y(jié)GC的耗時明顯縮短,性能將近提升50%!這歸功于分代收集的能力

YGC平均暫停時間

YGC次數(shù)

效果

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);        //復(fù)制幾遍字符串
long  lineCount = str.lines().count();  //行數(shù)統(tǒng)計


System.out.println(isblank);            //結(jié)果:false            
System.out.println(isempty);            //結(jié)果:false 
System.out.println(result1);            //結(jié)果:i am lzc 
System.out.println(result2);            //結(jié)果: i am lzc 
System.out.println(result3);            //結(jié)果:i am lzc  
System.out.println(copyStr);            //結(jié)果: i am lzc  i am lzc  
System.out.println(lineCount);          //結(jié)果: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"));

數(shù)據(jù)流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); //結(jié)果: [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); //結(jié)果: {1=a, 2=b, 3=c}

optional加強

//新增orElseThrow,為空時拋異常
Object v2 = Optional.ofNullable(null).orElseThrow();      //結(jié)果:拋異常


//新增ifPresentOrElse,不為null執(zhí)行第1個回調(diào)函數(shù),為null時執(zhí)行第2個回調(diào)函數(shù)
Optional.ofNullable(null).ifPresentOrElse(
        (x) -> {
            System.out.println("數(shù)據(jù):" + x);
        }, () -> {
            System.out.println("數(shù)據(jù)不存在");
        });


//提供另一個Optionals 作為空Optionals的回調(diào)
Object v3 = Optional.ofNullable(null)
        .or(() -> Optional.of("fallback"))
        .get();   //結(jié)果: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());

六、常見問題解決‌

  • JVM參數(shù)調(diào)整‌:移除-Xverify等廢棄參數(shù),替換為--add-opens解決模塊訪問限制。
  • 類路徑?jīng)_突‌:JDK 11默認(rèn)不包含javax.xml等包,需顯式添加依賴(如--add-modules=jdk.xml.dom)。

七、總結(jié)

 升級后需全面回歸測試,建議先在非生產(chǎn)環(huán)境驗證。建議使用jdeprscan‌:檢測廢棄API。

到此這篇關(guān)于jdk8升級到j(luò)dk11如何升級的真實案例(親身經(jīng)歷)的文章就介紹到這了,更多相關(guān)jdk8升級到j(luò)dk11內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java統(tǒng)計字符串單詞個數(shù)的方法解析

    java統(tǒng)計字符串單詞個數(shù)的方法解析

    在一些項目中可能需要對一段字符串中的單詞進行統(tǒng)計,本文在這里分享了一個簡單的demo,有需要的朋友可以拿去看一下
    2017-01-01
  • Spring中的@PostConstruct注解使用方法解析

    Spring中的@PostConstruct注解使用方法解析

    這篇文章主要介紹了Spring中的@PostConstruct注解使用方法解析,@PostConstruct注解是用來處理在@Autowired注入屬性后init()方法之前,對一些零散的屬性進行賦值的注解,需要的朋友可以參考下
    2023-11-11
  • 應(yīng)用Java泛型和反射導(dǎo)出CSV文件的方法

    應(yīng)用Java泛型和反射導(dǎo)出CSV文件的方法

    這篇文章主要介紹了應(yīng)用Java泛型和反射導(dǎo)出CSV文件的方法,通過一個自定義函數(shù)結(jié)合泛型與反射的應(yīng)用實現(xiàn)導(dǎo)出CSV文件的功能,具有一定的參考借鑒價值,需要的朋友可以參考下
    2014-12-12
  • FeignClient設(shè)置動態(tài)url方式

    FeignClient設(shè)置動態(tài)url方式

    文章介紹了如何在Spring Cloud環(huán)境下使用FeignClient實現(xiàn)負(fù)載均衡,通過配置Nacos和FeignClient屬性,可以實現(xiàn)服務(wù)間的負(fù)載均衡調(diào)用
    2024-11-11
  • JAVA十大排序算法之插入排序詳解

    JAVA十大排序算法之插入排序詳解

    這篇文章主要介紹了java中的插入排序,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • 關(guān)于spring中定時器的使用教程

    關(guān)于spring中定時器的使用教程

    大家應(yīng)該都有所體會,在很多實際的web應(yīng)用中,都有需要定時實現(xiàn)的服務(wù),下面這篇文章主要給大家介紹了關(guān)于spring中定時器的使用教程,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-06-06
  • Java編程實現(xiàn)比對兩個文本文件并標(biāo)記相同與不同之處的方法

    Java編程實現(xiàn)比對兩個文本文件并標(biāo)記相同與不同之處的方法

    這篇文章主要介紹了Java編程實現(xiàn)比對兩個文本文件并標(biāo)記相同與不同之處的方法,涉及java針對文本文件的讀取、遍歷、判斷等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • MyBatis批量添加數(shù)據(jù)2種實現(xiàn)方法

    MyBatis批量添加數(shù)據(jù)2種實現(xiàn)方法

    這篇文章主要介紹了MyBatis批量添加數(shù)據(jù)2種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • java利用JEXL實現(xiàn)動態(tài)表達式編譯

    java利用JEXL實現(xiàn)動態(tài)表達式編譯

    這篇文章主要介紹了java利用JEXL實現(xiàn)動態(tài)表達式編譯,系統(tǒng)要獲取多個數(shù)據(jù)源的數(shù)據(jù),并進行處理,最后輸出多個字段。字段的計算規(guī)則一般是簡單的取值最多加一點條件判斷,下面是具體的實現(xiàn)方法
    2021-04-04
  • Java中對象序列化與反序列化詳解

    Java中對象序列化與反序列化詳解

    這篇文章主要介紹了Java中對象序列化與反序列化,較為詳細(xì)的分析了java中對象序列化的概念、原理、實現(xiàn)方法及相關(guān)注意事項,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09

最新評論