主頁 > 後端開發 > 升級指南之JDK 11+ 新特性和AJDK

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

2023-03-08 07:20:41 後端開發

寫在前面:

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

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546033.html

標籤:Java

上一篇:詳解Xss 及SpringBoot 防范Xss攻擊(附全部代碼)

下一篇:MP 代碼生成器工具類

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more