JDK已經如火如荼的更新到了JDK 19,集團內也在推AJDK 11的升級,升級已然是一個大趨勢。本文主要是對體育營銷場景升級JDK 11,進行了整理與總結,希望對大家有所幫助。 ...
寫在前面:
JDK已經如火如荼的更新到了JDK 19,集團內也在推AJDK 11的升級,升級已然是一個大趨勢。本文主要是對體育營銷場景升級JDK 11,進行了整理與總結,希望對大家有所幫助。
JDK版本概述
Java 版本新特性
JDK 9
模塊化
/**
* Defines the JDBC API.
*
* @uses java.sql.Driver
*
* @moduleGraph
* @since 9
*/
// 聲明模塊
module java.sql {
// 聲明依賴模塊, transitive修飾符會導致依賴於當前模塊的其他模塊具有隱式依賴性。
requires transitive java.logging;
requires transitive java.transaction.xa;
requires transitive java.xml;
// 聲明哪些包是可以被其它模塊訪問
exports java.sql;
exports javax.sql;
// 使用語句(uses statement)和提供語句(provides statement)實現其服務
// 使用語句可以指定服務介面的名字,當前模塊就會發現它,使用 java.util.ServiceLoader類進行載入
uses java.sql.Driver;
}
介面支持私有方法
public interface TestInterface{
default void method(){ init(); }
default void anotherMethod(){ init(); }
private void init(){ System.out.println("Initializing");}
}
新增Stream API & 集合工廠方法
-
takeWhile
// 輸出 => abc
Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
.forEach(System.out::print);
-
dropWhile
// 輸出 => ef
Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
.forEach(System.out::print);
-
ofNullable
// 輸出 => 0
System.out.println(Stream.ofNullable(null).count());
-
集合工廠方法
// 通過java.util.Set 創建 不可變 的集合實例
Set<String> set = Set.of("A", "B", "C");
// 通過java.util.List 創建 不可變 的集合實例
List<String> list = List.of("A", "B", "C");
// 通過k1,v1,k2,v2,...,形式創建
Map<String, String> map = Map.of("A","V1","B","v2","C","v3");
// 通過 Map.entry 形式創建
Map<Integer, String> map1 = Map.ofEntries (
Map.entry(1, "v1"),
Map.entry(2, "v2"),
Map.entry(3, "v3"));
改進版 Try-With Resources
static String readData(String message) throws IOException {
Reader reader = new StringReader(message);
BufferedReader br = new BufferedReader(reader);
// 不需要重新聲明變數
try (br) {
return br.readLine();
}
}
G1 成為預設垃圾收集器
JDK 10
APPCDS 應用程式類數據共用
多線程並行 GC
局部變數類型推斷
var list = new ArrayList<String>();
list.add("hello,world!");
System.out.println(list);
ArrayList<String> list = new ArrayList();
list.add("hello,world!");
System.out.println(list);
線程-局部管控
基於Java的實驗性JIT編譯器Graal
JDK 11
String 增強
// 判斷字元串是否為空
" ".isBlank(); // true
// 去除字元串首尾空格
" JDK11 ".strip();// "JDK11"
// 去除字元串首部空格
" JDK11 ".stripLeading(); // "JDK11 "
// 去除字元串尾部空格
" JDK11 ".stripTrailing(); // " JDK11"
// 重覆字元串多少次
"JDK11 ".repeat(3); // "JDK11 JDK11 JDK11 "
// 返回由行終止符分隔的字元串集合
"A\nB\nC".lines().count(); // 3
支持TLS 1.3 協議
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());
Epsilon:低開銷垃圾回收器
飛行記錄器:JFR
JDK 12 ~ 14
G1 收集器優化
-
可中止的混合收集集合 :為了達到用戶提供的停頓時間目標,通過把要被回收的區域集(混合收集集合)拆分為強制和可選部分,使 G1 垃圾回收器能中止垃圾回收過程。G1 可以中止可選部分的回收以達到停頓時間目標。
-
及時返回未使用的已分配記憶體 :由於 G1 儘量避免完整的 GC,並且僅基於 Java 堆占用和分配活動來觸發併發周期,因此在許多情況下,除非從外部強制執行,否則它不會返還 Java 堆記憶體。JDK 12增強了 G1 GC,可以在空閑時自動將 Java 堆記憶體返回給操作系統。
SocketAPI 重構
動態 CDS 存檔
增強 switch
String result = switch (day) {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "工作日";
case "weekend" -> "周末";
default -> {
// yield 關鍵字 yield的是JDK13後的一個新特性,它主要的作用是進行程式的局部返回
yield "unknown";
}
};
System.out.println(result);
移除 CMS 垃圾收集器
JDK 15 ~ 16
文本塊
String content = """
JDK 10
JDK 11
JDK 12
""";
System.out.println(content);
JDK 10
JDK 11
JDK 12
Hidden Classes(隱藏類)
instanceof 模式匹配
// JDK 16之前
if (obj instanceof String) {
// 強制轉換後使用
String str = (String)o;
... use str ...
}
// JDK 16
if (o instanceof String str) {
// 直接使用str變數
... use s ...
}
記錄類
// 定義記錄類
public record Person(String name, Integer age) {
}
// ======
// 使用
Person person = new Person("張三", 16);
System.out.println(person);
ZGC 併發線程堆棧處理
JDK 17
增強的偽隨機數生成器
RandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of("L128X256MixRandom");
// 使用時間戳作為隨機數種子
RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
// 生成隨機數
randomGenerator.nextInt(10));
密封類
// 比如現在要限制 Person類 只能被這三個類繼承,不能被其他類繼承,可以這麼做
// 添加sealed修飾符,permits後面跟上只能被繼承的子類名稱
public sealed class Person permits Teacher, Worker, Student{ } //人
// 子類可以被修飾為 final
final class Teacher extends Person { }//教師
// 子類可以被修飾為 non-sealed,此時 Worker類就成了普通類,誰都可以繼承它
non-sealed class Worker extends Person { } //工人
// 任何類都可以繼承Worker
class AnyClass extends Worker{}
移除實驗性的 AOT 和 JIT 編譯器
刪除 Applet API
AJDK11專有特性
應用啟動加速 EagerAppCDS
代碼預熱技術JWarmup2
AppAOT
QuickStart框架
VectorAPI
為什麼升級?
目前大多數應用用的還是JDK 8,不知道高版本的JDK能帶來什麼收益,所以沒有動力去升級,我理解升級JDK版本帶來的收益核心有三點:
-
性能收益,從已升級的應用的數據來看,性能收益還是不錯的,後面詳細介紹
-
新特性, 高版本有更多的語法和功能供我們使用
-
業界主流趨勢 springboot 、netty、Kafka這些常用的框架在高版本里已不再支持低版本JDK(JDK8及以下)
如何選擇版本?
AJDK11+G1升級收益
體育營銷中心
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其它案例
SPECjbb2015 JDK8/11性能分析
TPP
MTOP
升級指南
常用軟體升級
-
IntelliJ IDEA: 2018.2[2]
-
Eclipse: Photon 4.9RC2 with Java 11 plugin[3]
-
Maven: 3.5.0
-
compiler plugin: 3.8.0
-
surefire and failsafe: 2.22.0
-
Gradle: 5.0[4]
常用框架支持JDK11的最低版本:
-
ASM : 7.0 -
Spring : 5.0 -
Guice : 4.2 -
guava : 19.0
本地環境升級
-
本地開發可以在這裡[5]選擇合適的版本進行下載 (AJDK11只支持Linux操作系統)
-
項目配置新版本JDK 11
Linux部署環境升級
-
修改 ${app}.release 文件 的 baseline.jdk
# 構建打包使用jdk版本, aone編譯機器上未安裝最新版本的ajdk,
# 可以用已安裝的ajdk版本進行編譯,實際運行用最新版本的ajdk,最新版本的ajdk有較多新特性
baseline.jdk=ajdk11_11.0.14.13_fp2
# 升級maven版本,建議用amaven, amaven有代碼編譯加速的功能
build.tools.maven=amaven3.5.0
-
dockerfile修改
# 安裝ajdk11 最新版本的jdk可以在這裡查看 http://yum.tbsite.net/taobao/7/x86_64/current/ajdk11/
rpm -ivh --nodeps "http://yum.tbsite.net/taobao/7/x86_64/current/ajdk11/ajdk11-11.0.16.15_fp1-20220929100209.alios7.x86_64.rpm" && \
# 把java目錄軟鏈到 /opt/taobao/java 目錄,ajdk8自動連接,ajdk11 需要手動軟鏈
rm -rf /opt/taobao/java && ln -s /opt/taobao/install/ajdk11-11.0.16.15_fp1 opt/taobao/java && \
-
setenv.sh 腳本修改
# 去掉cms相關參數,刪除下麵兩行
SERVICE_OPTS="${SERVICE_OPTS} -XX:+UseConcMarkSweepGC -XX:CMSMaxAbortablePrecleanTime=5000"
SERVICE_OPTS="${SERVICE_OPTS} -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly"
遇到的問題
aone編譯機器上未安裝相應的jdk
-
aone發佈編譯報錯
-
原因是目前ajdk 11 只在aone編譯機器上安裝了部分版本,未升級到最新版本
-
解決方案:
-
編譯AJDK版本可以用aone編譯機器上已安裝的版本
-
申請請安裝新版本的ajdk
應用啟動報錯 io.netty.util.internal.PlatformDependent0 - direct buffer constructor: unavailable
-
報錯截圖
-
解決方式:setenv.sh 腳本增加如下參數。
SERVICE_OPTS="${SERVICE_OPTS} -Dio.netty.tryReflectionSetAccessible=true --add-opens=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED"
QuickStart框架集成
總結
[1]https://newrelic.com/resources/report/2022-state-of-java-ecosystem
[2]https://blog.jetbrains.com/idea/2018/06/java-11-in-intellij-idea-2018-2/
[3] https://blog.codefx.org/https://marketplace.eclipse.org/content/java-11-support-eclipse-photon-49
[4]https://docs.gradle.org/5.0/release-notes.html#java-11-runtime-support
本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/Upgrade-Guide-JDK-11-New-Features-and-AJDK.html