升級指南之JDK 11+ 新特性和AJDK

来源:https://www.cnblogs.com/88223100/archive/2023/03/07/Upgrade-Guide-JDK-11-New-Features-and-AJDK.html
-Advertisement-
Play Games

JDK已經如火如荼的更新到了JDK 19,集團內也在推AJDK 11的升級,升級已然是一個大趨勢。本文主要是對體育營銷場景升級JDK 11,進行了整理與總結,希望對大家有所幫助。 ...


寫在前面:

JDK已經如火如荼的更新到了JDK 19,集團內也在推AJDK 11的升級,升級已然是一個大趨勢。本文主要是對體育營銷場景升級JDK 11,進行了整理與總結,希望對大家有所幫助。

JDK版本概述

從1996年初JDK1.0發佈到現在已經二十多年了, 最新一個版本已經到 JDK 19,JDK17是最新的一個LTS(Long-Term Support)版本。所謂LTS版本就是可以得到至少八年產品支持的版本。到目前為止,有四個LTS版本,JDK 7、JDK 8、JDK 11、JDK 17,下一個LTS版本是JDK 21,預計在2023年9月發佈。Oracle 每隔6個月就會有一個短期維護版本(non-LTS)發佈出來;然後每隔2年,就會發佈一款得到8年長期支持維護的JDK版本,下圖是oracle官方發佈的roadmap, 可以更直觀的看到JDK版本的更新, 這個發佈節奏著實讓人有點追不上啊。
圖片

Java 版本新特性

圖片
上圖顯示了自 Java 8 起到 Java 19 各版本新增特性的數量。從 Java 8 到 Java 19 總共引入了超過 250 個新特性,其中 Java 9 中包含了 91 個新特性,這是由於之前的發佈周期較長所導致的,在應用新的發佈模型後,各版本的新增特性數量都維持在 10 個左右的水平。下麵主要針對各版本的主要特性進行介紹

JDK 9

模塊化

模塊化提供了比 package 更高級別的聚合,模塊是一個包的容器。模塊的代碼被組織成多個包,每個包中包含Java類和介面;如果我們想讓項目成為一個模塊,則需要在該項目的java源碼的根目錄(如果是maven項目也就是src/main/java)添加一個特殊的java文件模塊描述符文件 module-info.java,以jdk 里java.sql 模塊為例:
圖片
/**
 * 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;
}

介面支持私有方法

JDK 8 為我們帶來了介面的預設方法。介面現在也可以包含行為,而不僅僅是方法簽名。JDK 9支持了私有方法,可以解決介面中代碼復用問題;該特性主要是為了Java 8中default方法和static方法服務的。

public interface TestInterface{
    
    default void method(){ init(); }
    
    default void anotherMethod(){ init(); }
        
    private void init(){ System.out.println("Initializing");}
}

新增Stream API & 集合工廠方法

JDK 9 為 Stream 新增了幾個方法:dropWhile、takeWhile、ofNullable,為 iterate 方法新增了一個重載方法。
  • takeWhile
takeWhile 方法使用一個斷言作為參數,返回給定 Stream 的子集直到斷言語句第一次返回 false。如果第一個值不滿足斷言條件,將返回一個空的 Stream。

// 輸出 => abc
Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
         .forEach(System.out::print);      
  • dropWhile
dropWhile 方法和 takeWhile 作用相反的,使用一個斷言作為參數,直到斷言語句第一次返回 true 才返回給定 Stream 的子集。

// 輸出 => ef
Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
         .forEach(System.out::print);
  • ofNullable
ofNullable 方法可以預防 NullPointerException 異常, 可以通過檢查流來避免 null 值。

// 輸出 => 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

try-with-resources 是 JDK 7 中一個新的異常處理機制,它能夠很容易地關閉在 try-catch 語句塊中使用的資源。try-with-resources 聲明在 JDK 9 已得到改進。如果你已經有一個資源是 final 或等效於 final 變數,您可以在 try-with-resources 語句中使用該變數,而無需在 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 成為預設垃圾收集器

在 Java 8 的時候,預設垃圾回收器是 Parallel Scavenge(新生代)+Parallel Old(老年代)。到了 Java 9, CMS 垃圾回收器被廢棄了,G1(Garbage-First Garbage Collector) 成為了預設垃圾回收器。G1 是在 Java 7 中被引入的,經過兩個版本優異的表現成為成為預設垃圾回收器。

JDK 10

APPCDS 應用程式類數據共用

CDS 的全稱是 Class-Data Sharing, CDS 的作用是讓類可以被預處理放到一個歸檔文件中,後續 Java 程式啟動的時候可以直接帶上這個歸檔文件,這樣 JVM 可以直接將這個歸檔文件映射到記憶體中,以節約應用啟動的時間。這個特性在 JDK 1.5 就開始引入, 但是 CDS 只能作用與 Boot Class Loader 載入的類,不能作用於 App Class Loader 或者自定義的 Class Loader 載入的類。在 JDK 10 中, CDS 擴展為 AppCDS,AppCDS 不止能夠作用於 Boot Class Loader,App Class Loader 和自定義的 Class Loader 也都能夠起作用,進一步提高了應用啟動性能。

多線程並行 GC

在JDK9中G1被選定為預設的垃圾收集器,G1的設計目標是避免發生Full GC,由於Full GC較難產生所以在設計之初只有Young GC和Mixed GC是並行的,而Full GC是單線程使用標記-清理-合併演算法進行垃圾回收。G1只是避免發生Full GC,在極端情況下,當G1的回收速度相對於產生垃圾的速度不是足夠快時,就會發生Full GC。
為了最大限度地減少 Full GC 造成的應用停頓的影響,從 JDK 10開始,G1 的 FullGC 改為並行的標記清除演算法,同時會使用與年輕代回收和混合回收相同的並行工作線程數量,從而減少了 Full GC 的發生,以帶來更好的性能提升、更大的吞吐量
線程的數量可以由 -XX:ParallelGCThreads 選項來控制,這個參數也用來控制Young GC和Mixed GC的線程數。

局部變數類型推斷

JDK10 可以使用var作為局部變數類型推斷標識符,此符號僅適用於局部變數,增強for迴圈的索引,以及傳統for迴圈的本地變數;它不能使用於方法形式參數,構造函數形式參數,方法返回類型,欄位,catch形式參數或任何其他類型的變數聲明。
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);
從示例中可以看出,var 其實是一種語法糖,旨在改善開發者體驗

線程-局部管控

這是在 JVM 內部相當低級別的更改,現在將允許在不運行全局虛擬機安全點的情況下實現線程回調。這將使得停止單個線程變得可能和便宜,而不是只能啟用或停止所有線程。

基於Java的實驗性JIT編譯器Graal

Graal 是一個以 Java 為主要編程語言,面向 Java bytecode 的編譯器。與用 C++ 實現的 C1 及 C2 相比,它的模塊化更加明顯,也更加容易維護。Graal 既可以作為動態編譯器,在運行時編譯熱點方法;亦可以作為靜態編譯器,實現 AOT 編譯。在 JDK 10 中,Graal 作為試驗性 JIT compiler 一同發佈

JDK 11

String 增強

JDK 11 增加了一系列的字元串處理方法:

// 判斷字元串是否為空
" ".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 協議

實現TLS協議1.3版本, 替換了之前版本中包含的 TLS,包括 TLS 1.2,同時還改進了其他 TLS 功能, 在安全性和性能方面也做了很多提升

HTTP Client

在 JDK 11 中 Http Client API 得到了標準化的支持。且支持 HTTP/1.1 和 HTTP/2 ,也支持 websockets。
使用起來也很簡單,如下:
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:低開銷垃圾回收器

新增的垃圾回收器,一個完全消極的 GC 實現,分配有限的記憶體資源,最大限度的降低記憶體占用和記憶體吞吐延遲時間

飛行記錄器:JFR

Java飛行記錄器(Java Flight Recorder)已經變成JDK 11的一部分了,之前它是一個商業功能,但是伴隨JDK 11發佈,它從OracleJDK開源到了OpenJDK。
飛行記錄器類似飛機上的黑盒子,是一種低開銷的事件信息收集框架,主要用於對應用程式和 JVM 進行故障檢查、分析。飛行記錄器記錄的主要數據源於應用程式、JVM 和 OS,這些事件信息保存在單獨的事件記錄文件中,故障發生後,能夠從事件記錄文件中提取出有用信息對故障進行分析

JDK 12 ~ 14

G1 收集器優化

JDK 12 為垃圾收集器 G1 帶來了兩項更新
  • 可中止的混合收集集合 :為了達到用戶提供的停頓時間目標,通過把要被回收的區域集(混合收集集合)拆分為強制和可選部分,使 G1 垃圾回收器能中止垃圾回收過程。G1 可以中止可選部分的回收以達到停頓時間目標。

  • 及時返回未使用的已分配記憶體 :由於 G1 儘量避免完整的 GC,並且僅基於 Java 堆占用和分配活動來觸發併發周期,因此在許多情況下,除非從外部強制執行,否則它不會返還 Java 堆記憶體。JDK 12增強了 G1 GC,可以在空閑時自動將 Java 堆記憶體返回給操作系統。

SocketAPI 重構

java.net.Socket 和 java.net.ServerSocket 類早在 Java 1.0 時就已經引入了,它們的實現的 Java 代碼和 C 語言代碼的混合,維護和調試都十分不易;而且這個實現還存在併發問題,有時候排查起來也很困難。JDK 13 將 Socket API 的底層進行了重寫,並且在 JDK 13 中是預設使用新的 Socket 實現, 使其易於排查問題,同時也增加了可維護性。

動態 CDS 存檔

JDK 13 中對 JDK 10 中引入的應用程式類數據共用(AppCDS)進行了進一步的簡化、改進和擴展,即:允許在 Java 應用程式執行結束時動態進行類歸檔,具體能夠被歸檔的類包括所有已被載入,但不屬於預設基層 CDS 的應用程式類和引用類庫中的類。這提高了應用程式類數據共用AppCDS的可用性。

增強 switch 

增強版 switch 在 JDK 12 作為預覽特性引入。在 JDK 14 之後,增強版 switch 語句塊具備返回值
    String result = switch (day) {
            case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" -> "工作日";
            case "weekend" -> "周末";
            default -> {
                // yield 關鍵字 yield的是JDK13後的一個新特性,它主要的作用是進行程式的局部返回
                yield "unknown";
            }

        };
System.out.println(result);

移除 CMS 垃圾收集器

移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退)

 

JDK 15 ~ 16

文本塊

JDK 15正式發佈文本塊功能, 用來解決多行文本的問題,文本塊以三重雙引號開頭,並以同樣的以三重雙引號結尾終止
示例:

String content = """
    JDK 10
    JDK 11
    JDK 12
 """;
System.out.println(content);
輸出:
JDK 10
JDK 11
JDK 12

Hidden Classes(隱藏類)

此功能可幫助需要在運行時生成類的框架。框架生成類需要動態擴展其行為,但是又希望限制對這些類的訪問。隱藏類很有用,因為它們只能通過反射訪問,而不能從普通位元組碼訪問。此外,隱藏類可以獨立於其他類載入,這可以減少框架的記憶體占用。

instanceof 模式匹配

之前使用instanceof 進行類型判斷之後,需要進行對象類型轉換後才能使用。而在 JDK 16 中,可以在判斷類型時指定變數名稱進行類型轉換,方便了使用。
// JDK 16之前
if (obj instanceof String) {
    // 強制轉換後使用
    String str = (String)o;
    ... use str ...
}

// JDK 16
if (o instanceof String str) {
    // 直接使用str變數
    ... use s ...
}

記錄類

record 是一種全新的類型,它本質上是一個 final 類,同時所有的屬性都是 final 修飾,或者可看成是 Lombok 中 @Data 註解的一個 "低配" 替代。它會自動編譯出 getXXX、toString、 hashcode 、equals等方法,減少了代碼編寫量。
// 定義記錄類
public record Person(String name, Integer age) {
}

// ======

// 使用
Person person = new Person("張三", 16);
System.out.println(person);

ZGC 併發線程堆棧處理

ZGC是JDK 11引入的新的垃圾收集器,JDK 15 正式發佈成正式特性,ZGC是一個重新設計的併發的垃圾回收器,可以極大的提升GC的性能。支持任意堆大小而保持穩定的低延遲(10ms以內),性能非常可觀。
JDK 16將 ZGC 線程棧處理從安全點轉移到一個併發階段,甚至在大堆上也允許在毫秒內暫停 GC 安全點。消除 ZGC 垃圾收集器中最後一個延遲源可以極大地提高應用程式的性能和效率。

JDK 17

增強的偽隨機數生成器

JDK 17 之前,我們可以藉助 Random、ThreadLocalRandom和SplittableRandom來生成隨機數。不過,這 3 個類都各有缺陷,且缺少常見的偽隨機演算法支持。
JDK 17 為偽隨機數生成器 (pseudorandom number generator,RPNG,又稱為確定性隨機位生成器)增加了新的介面類型和實現,使得開發者更容易在應用程式中互換使用各種 PRNG 演算法。
使用示例:
RandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of("L128X256MixRandom"); 
// 使用時間戳作為隨機數種子
RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());
// 生成隨機數
randomGenerator.nextInt(10));

密封類

密封類可以是封閉類和或者封閉介面,用來增強 Java 編程語言,防止其他類或介面擴展或實現它們。這個特性由JDK 15的預覽版本在JDK 17晉升為正式版本。
密封類引入了sealedclass或interface,這些class或者interfaces只允許被指定的類或者interface進行擴展和實現。使用修飾符sealed,可以將一個類聲明為密封類。密封的類使用關鍵字permits列出可以直接擴展它的類。子類可以是最終的,非密封的或密封的。
// 比如現在要限制 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 編譯器

實驗性的基於 Java 的提前 (AOT) 和即時 (JIT) 編譯器是實驗性功能,並未得到廣泛採用。作為可選,它們已經從 JDK 16 中刪除。這個 JEP 從 JDK 源代碼中刪除了這些組件。

刪除 Applet API 

Applet 是使用 Java 編寫的可以嵌入到 HTML 中的小應用程式,嵌入方式是通過普通的 HTML 標記語法,由於早已過時,幾乎沒有場景在使用了。Applet API 在 JDK 9 時已經標記了廢棄,現在 JDK 17 中徹底刪除

AJDK11專有特性

AJDK是集團JVM 團隊在 Java Standard Edition (SE) 規範下的 OpenJDK 基礎上自主研發的 JDK 版本,開源版本是Alibaba Dragonwell 

應用啟動加速 EagerAppCDS

針對阿裡的應用場景,對AppCDS進行優化, 縮短應用啟動時間

代碼預熱技術JWarmup2

JWarmup是AJDK 8引入的一個功能,主要是解決線上應用代碼預熱的問題,JWarmup2在JWarmup1基礎上開發,使用更便捷,性能更優。

AppAOT

AOT(ahead of time)是一項新的Java編譯技術,不同於我們習慣的Jit(Just in time)編譯,AOT在應用運行前就把一部分代碼編譯好,這樣在啟動的時候可以節省編譯時間,減少CPU使用,加速啟動。

QuickStart框架

QuickStart集成了AppCDS、EagerAppCDS、AOT等多種特性,旨在提升應用啟動性能。

VectorAPI

Vector API是OpenJDK project Panama的一個重要組成部分,它的目標是讓Java開發者更加自由的調用CPU強大的SIMD指令,讓一條指令處理多條數據,從而獲得成倍的性能提升。Vector API在大數據,AI計算和多媒體處理等。

為什麼升級?

目前大多數應用用的還是JDK 8,不知道高版本的JDK能帶來什麼收益,所以沒有動力去升級,我理解升級JDK版本帶來的收益核心有三點:

  1. 性能收益,從已升級的應用的數據來看,性能收益還是不錯的,後面詳細介紹

  2. 新特性, 高版本有更多的語法和功能供我們使用

  3. 業界主流趨勢 springboot 、netty、Kafka這些常用的框架在高版本里已不再支持低版本JDK(JDK8及以下)

如何選擇版本?

首選 LTS版本, JDK 8以後LTS版本目前就兩個,JDK 11和 JDK17, 對應集團內的版本就是AJDK 11和 AJDK 17, 直接從JDK 8 -> JDK 17, 風險較高,由於沒有經過JDK 11過渡,可能會出現測試未覆蓋代碼線上上運行時直接異常退出情況。
總的來看,目前選擇JDK11是一個不錯的選擇,建議大家可以先升級JDK11, 如果有需求再升級JDK17, 如果有的同學對應用的代碼和依賴完全可控, 可以直接升AJDK 17。
另外附上New Relic 2022年3月發佈的一份 Java 生態系統狀況報告[1] 供參考,該報告基於從數百萬個提供性能數據的匿名應用程式中收集的數據。報告顯示,JDK 11 採用率已經超過 JDK 8,已經成為生產環境的最新標準。
圖片

AJDK11+G1升級收益

主要從自己實踐的應用及集團內已升級的應用,升級前後的數據來看性能收益 。

體育營銷中心

升級後進行壓測,兩個版本的壓測數據如下:
 
GC平均次數
GC平均耗時
介面平均RT
介面最大RT
CPU利用率
AJDK 8 + CMS
28.63 
1445.00ms
44.19ms
1787.42ms
96.14%
AJDK 11 + G1
14.75
160.25ms
32.97ms
1448.79ms
92.72%
圖片
圖片
總的來看,升級後GC次數下降48%, GC平均耗時下降88%,介面平均RT降低25%,CPU利用率下降3.5%
從上面兩張圖可以看出,應對突發流量的情況JDK 11也優於JDK 8。

其它案例

SPECjbb2015 JDK8/11性能分析

SPECjbb2015是SPEC組織的一個用於評估伺服器端Java應用性能的基準測試程式。
圖片
圖片

TPP

TPP升級後JDK版本後主要降低了P99指標。
店鋪投放場景在應對突發流量的情況,升級JDK 11後超時Y率從6.58%降低至1.65%。
手猜工程場景,超時率從1.3%左右下降到了1.3‰左右,SLA從2個9變成了3個9,gc的次數跟gc耗時都有下降。

MTOP

MTOP 升級 JDK 11 + G1 GC 後,單機QPS 提升 11%, CPU 降低 2 pt, RT 降低 5%,YGC 平均次數 和 平均暫停時長均 降低 40-50% ,落到成本上可以縮減 MTOP 機器 10% 即 100 台左右 。

升級指南

常用軟體升級

一些常用軟體或框架的老版本不支持JDK11,需要進行升級。
常用的開發軟體和插件的支持JDK11的最低版本:
  • 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

本地環境升級

    1. 本地開發可以在這裡[5]選擇合適的版本進行下載 (AJDK11只支持Linux操作系統)

    2. 項目配置新版本JDK 11

圖片
圖片
圖片

Linux部署環境升級

  1. 修改 ${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
  1. 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 && \
  1. 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框架集成

目前我只在預發環境測試了其加速效果,應用啟動時間從 40s 左右 可以降低至25s左右。還未來得及在生產環境中實踐,不過JVM團隊大佬給出了幾個在生產環境落地的方案,大家可以參考下,後續有實踐後再更新 。
圖片
圖片

總結

本文主要講了JDK高版本的一些新特性、升級JDK 11帶來的收益以及升級步驟和升級常見問題。總體來說, JDK 11 升級帶來的收益是大於升級成本的(特別老的應用另說),希望本文能夠幫助大家對高版本的JDK有一個全面的瞭解,對於有升級需要的同學也能有所幫助。
參考鏈接:

[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

[5]https://adoptium.net/zh-CN/marketplace/?version=11
作者|劉兵(多葉)

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/Upgrade-Guide-JDK-11-New-Features-and-AJDK.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 術語 1.1. 堆指代Java堆 1.2. 原生記憶體指代JVM的非堆記憶體 1.2.1. 包括C堆 1.2.2. 非堆記憶體就是原生記憶體 1.2.3. 一些常見的JDK類常常會使用原生記憶體,請確保正確使用這些類 1.3. 一個應用程式總的記憶體占用 1.3.1. JVM使用的原生記憶體和堆記憶體的總和 ...
  • VL50 簡易秒錶 `timescale 1ns/1ns module count_module( input clk, input rst_n, output reg [5:0]second, output reg [5:0]minute ); always@(posedge clk or neg ...
  • 今天我們分享一個用Python寫下載視頻+彈幕+評論的代碼。 之前自游寫了採集小破站視頻、彈幕、評論的代碼,還錄了視頻。 我當時就問他,你就不能把這些寫成GUI,把這些功能放到一起不是別人用起來更方便麽? 本來他還想反抗,當時我就直接叫他看著辦! 他哪受得了這種委屈,當時就乖乖寫代碼去了,現在我把代 ...
  • 在這裡簡述一下什麼是邏輯刪除,對於我們資料庫表的設計,其中許多表會有一個status欄位(就是標記當條數據是否顯示在前端,也有叫做deleteflag),當他標記為0或者1即為刪除,此僅僅表示不顯示該數據,當時資料庫中還是需要此數據。 好了,接下來上乾貨 首先在我們的config目錄(沒有就新建一個 ...
  • 一、引入 class OldboyStudent: school = 'oldboy' def choose_course(self): print('is choosing course') stu1 = OldboyStudent() stu2 = OldboyStudent() stu3 = ...
  • 一篇搞懂cookie和session cookie、session和token存在的意義是什麼? http是無狀態的,每次請求是獨立的,服務端不保存會話信息,所以他的好處也就是快,但缺點也顯而易見,就是無法對不同用戶進行區分。 什麼是cookie? cookie存儲於客戶端,請求後由伺服器發送回瀏覽 ...
  • 1. 問題 golang構建程式很簡單,當遇到需要調用c庫時,如通常使用 net,kafka, sqlite3 程式運行時就會調用當前伺服器的 動態庫,如果遇到沒有庫時,通常還需要 下載比如 alpine需要安裝sqlite apk add --no-cache sqlite-libs sqlite ...
  • Mybatis-Plus 代碼生成器工具類 對 MP 的代碼生成器寫一個簡單的工具類: public class Main { public static String scanner(String tip) { Scanner scanner = new Scanner(System.in); S ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...