一、背景與挑戰(zhàn)
1.升級(jí)動(dòng)因
?Oracle長期支持策略
?現(xiàn)代特性需求:協(xié)程、模式匹配、ZGC等
?安全性與性能的需求
?AI新技術(shù)引入的版本要求
2.項(xiàng)目情況
?100+項(xiàng)目并行升級(jí)的協(xié)同作戰(zhàn)
?多技術(shù)棧并存
?持續(xù)集成體系的適配挑戰(zhàn)
?
二、進(jìn)度
應(yīng)用總數(shù) | 已完成 | 應(yīng)用下線 | 待升級(jí) |
100+ | 73 | 13 | 10+ |
?
三、主要問題域與解決方案
1. 依賴管理的"蝴蝶效應(yīng)"
?sun.misc.BASE64Encoder等內(nèi)部API廢棄 → 引發(fā)編譯錯(cuò)誤
?JAXB/JAX-WS從JDK核心剝離 → XML處理鏈斷裂
?Lombok與新版編譯器兼容性問題(尤其record類型)
核心原因在于JEP320提案:https://openjdk.org/jeps/320?
?
案例1:歷史SDK的編譯陷阱
Compilation failure: Compilation failure: #14 4.173 [ERROR] 不再支持源選項(xiàng) 6。請使用 8 或更高版本。 #14 4.173 [ERROR] 不再支持目標(biāo)選項(xiàng) 6。請使用 8 或更高版本。
!-- 舊版本編譯器配置導(dǎo)致構(gòu)建失敗 --?> org.apache.maven.plugins/groupId?> maven-compiler-plugin/artifactId?> 3.5/version?> 1.6/source?> 1.6/target?> /configuration?> /plugin?>
org.apache.maven.plugins/groupId?> maven-compiler-plugin/artifactId?> 3.13.0/version?> 8/release?>!-- 統(tǒng)一使用release參數(shù) --?> /configuration?> /plugin?>
運(yùn)行 HTML
案例2:JAXB的模塊化剝離
javax.xml.bind.JAXBException:Implementation of JAXB-API has not been found
org.glassfish.jaxb/groupId?> jaxb-runtime/artifactId?> 4.0.5/version?> /dependency?>
案例3:Lombok與新版編譯器兼容性問題
java: java.lang.NoSuchFieldError
org.projectlombok/groupId?> lombok/artifactId?> 1.18.30/version?> /dependency?>
案例4:Resource注解找不到
Caused by: java.lang.NoSuchMethodError: 'java.lang.String javax.annotation.Resource.lookup()' at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.(CommonAnnotationBeanPostProcessor.java:664) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.lambda$buildResourceMetadata$0(CommonAnnotationBeanPostProcessor.java:395) at org.springframework.util.ReflectionUtils.doWithLocalFields(ReflectionUtils.java:669) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.buildResourceMetadata(CommonAnnotationBeanPostProcessor.java:377) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.findResourceMetadata(CommonAnnotationBeanPostProcessor.java:358) at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:306) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1116) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ... 37 more
jakarta.annotation/groupId?> jakarta.annotation-api/artifactId?> 1.3.5/version?> /dependency?> javax.annotation/groupId?> javax.annotation-api/artifactId?> 1.3.2/version?> /dependency?>
上述兩個(gè)依賴代碼基本一樣,推薦使用該版本:
jakarta.annotation:jakarta.annotation-api。
?
2. 模塊化的破與立
反射訪問的模塊墻
[ERROR] Unable to make field private int java.text.SimpleDateFormat.serialVersionOnStream accessible
# 啟動(dòng)參數(shù)添加模塊開放配置 --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
完整模塊開放配置模板
export JAVA_OPTS="-Djava.library.path=/usr/local/lib -server -Xmx4096m --add-opens 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 --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-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/sun.security.action=ALL-UNNAMED --add-opens java.base/sun.net.util=ALL-UNNAMED --add-opens java.base/java.time=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED"
3. 語法層面的"時(shí)空穿越"
案例1:Base64編解碼改造
// JDK8寫法(已廢棄) BASE64Encoder encoder =newBASE64Encoder(); String encoded = encoder.encode(data); // JDK21規(guī)范寫法 Base64.Encoder encoder =Base64.getEncoder(); String encoded = encoder.encodeToString(data);
案例2:日期序列化問題
Caused by:java.lang.reflect.InaccessibleObjectException: Unable to make field private int java.text.SimpleDateFormat.serialVersionOnStream accessible
解決方案
1.使用DateTimeFormatter替代SimpleDateFormat
2.或添加模塊開放參數(shù):--add-opens java.base/java.text=ALL-UNNAMED
?
4. 隱秘的"依賴戰(zhàn)爭"
注解包沖突典型案例
[ERROR] javax.annotation.Resource exists in both jsr250-api-1.0.jar and jakarta.annotation-api-1.3.5.jar
!-- 統(tǒng)一使用Jakarta標(biāo)準(zhǔn) --?> jakarta.annotation/groupId?> jakarta.annotation-api/artifactId?> 2.1.1/version?> /dependency?> !-- 排除舊版本依賴 --?> javax.annotation/groupId?> jsr250-api/artifactId?> /exclusion?> /exclusions?>
5. 構(gòu)建體系的改造
Maven插件兼容性問題
[ERROR] The plugin org.apache.maven.plugins:maven-compiler-plugin:3.13.0 requires Maven version 3.6.3
升級(jí)策略
1.升級(jí)Maven版本
2.統(tǒng)一插件版本
org.apache.maven.plugins/groupId?> maven-compiler-plugin/artifactId?> 3.13.0/version?> /plugin?> org.apache.maven.plugins/groupId?> maven-war-plugin/artifactId?> 3.4.0/version?> /plugin?> /plugins?> /pluginManagement?> /build?>
四、最佳實(shí)踐總結(jié)
1. 本地編譯
第一步:在本地進(jìn)行編譯,提前識(shí)別出語法錯(cuò)誤、版本沖突及不兼容問題。
主要有以下幾種場景:
Base64:參照 【Base64編解碼改造】
lombok:升級(jí)版本
jsr250、jaxb-runtime、jakarta.annotation-api:參照 【注解包沖突典型案例】
maven-compiler-plugin:升級(jí)版本
maven-resources-plugin:升級(jí)版本
maven-war-plugin:升級(jí)版本
?
?
2. 行云構(gòu)建
同【本地編譯】
?
3. 行云部署
a、鏡像不匹配:自定義鏡像或者使用已申請的jdk21鏡像
b、module權(quán)限不夠:參照【完整模塊開放配置模板】
c、JDSecurity加解密
所有數(shù)據(jù)庫操作:important.properties配置文件的處理方式
classpath:important.properties 使用PropertyPlaceholderConfigurer進(jìn)行處理,不要用JDSecurityPropertyFactoryBean。
!-- --?> !-- --> !-- --> !-- /bean?>-->
?
4. 運(yùn)行
a、序列化異常
jdk21使用列表視圖作為入?yún)ⅲ瑢?dǎo)致jsf接口進(jìn)行反序列化報(bào)錯(cuò)。報(bào)錯(cuò)代碼如下:
List subList = venderCodes.subList(i * batchSize, Math.min(venderCodes.size(), (i + 1) * batchSize)); VendorQueryVo vendorQueryVo = new VendorQueryVo(); vendorQueryVo.setVendorCodes(subList); // 該接口最多支持100條調(diào)用 List batchVendorNameByVendorCode = vendorBaseInfoService.getBatchVendorNameByVendorCode(vendorQueryVo, I18NParamFactory.getJDI18nParam());
將 vendorQueryVo.setVendorCodes(subList) 修改為vendorQueryVo.setVendorCodes(new ArrayList<>(subList)) 即可解決問題
?
b、線程上下文類找不到:使用多線程場景下盡可能使用顯式指定線程池【默認(rèn)情況下 不同運(yùn)行環(huán)境的處理機(jī)制不同】
?
?
5. JVM調(diào)優(yōu)
垃圾回收調(diào)優(yōu)
UseParallelGC、UseG1GC和UseZGC是 Java 虛擬機(jī)(JVM)中三種不同的垃圾回收器(Garbage Collector, GC),它們的設(shè)計(jì)目標(biāo)和使用場景有所不同。以下是它們的區(qū)別:
特性 | UseParallelGC | UseG1GC | UseZGC |
設(shè)計(jì)目標(biāo) | 高吞吐量 | 平衡吞吐量和延遲 | 極低延遲 |
暫停時(shí)間 | 較長 | 較短 | 極短 |
適用堆大小 | 中小堆(幾 GB 到幾十 GB) | 大堆(幾十 GB 到幾百 GB) | 超大堆(TB 級(jí)別) |
CPU 消耗 | 中等 | 中等 | 較高 |
適用場景 | 批處理、計(jì)算密集型任務(wù) | 對延遲有一定要求的應(yīng)用 | 對延遲極其敏感的應(yīng)用 |
?如果你的應(yīng)用對吞吐量要求高,且可以接受較長的暫停時(shí)間,選擇UseParallelGC。
?如果你的應(yīng)用對延遲有一定要求,且堆內(nèi)存較大,選擇UseG1GC。
?如果你的應(yīng)用對延遲極其敏感,且堆內(nèi)存非常大,選擇UseZGC。
僅供參考,具體請按照實(shí)際情況來進(jìn)行調(diào)整。
審核編輯 黃宇
-
JDK
+關(guān)注
關(guān)注
0文章
83瀏覽量
16827
發(fā)布評(píng)論請先 登錄
STM32MP157d linux從5.4.31升級(jí)到6.1.82無法啟動(dòng)怎么解決?
STM32MP157d linux從5.4.31升級(jí)到6.1.82無法啟動(dòng)怎么解決?
STM32MP157d linux從5.4.31升級(jí)到6.1.82無法啟動(dòng)怎么解決?
STM32MP157d linux從5.4.31升級(jí)到6.1.82無法啟動(dòng)的原因?
6.12.1升級(jí)到6.13老是閃退是什么原因?qū)е碌模?/a>
從ADS7813升級(jí)到ADS8513

從JESD204B升級(jí)到JESD204C時(shí)的系統(tǒng)設(shè)計(jì)注意事項(xiàng)

將Non-OS SDK從1.3.0升級(jí)到1.4.0后,AT CWLAP命令將無法再找到我的AP,為什么?
OTA升級(jí)從user2.bin ota升級(jí)到user1.bin失敗了的原因?
JDK8升級(jí)JDK11最全實(shí)踐干貨來了

JDK11升級(jí)JDK17最全實(shí)踐干貨來了

評(píng)論