之前寫過一篇 從 Java 8 到 25 的版本演進,把五個 LTS 的重點功能整理成一條線。那篇的定位是「對照地圖」,每個特性點到為止。這篇換個角度,專門看 Java 25、26、27 這三個版本。

Java 25 是 2025 年 9 月發佈的 LTS,目前多數生產環境的升級目標。Java 26 是 2026 年 3 月的非 LTS 版本。Java 27 預計 2026 年 9 月 14 日發佈,同樣是非 LTS,下一個 LTS 要等到 Java 29。

Java 25 — 目前的 LTS

Java 25 共 18 個 JEP,其中 7 個正式定案。對多數開發者來說,影響較大的是以下幾個。

Compact Source Files 與 Instance Main(JEP 512)

從 Java 21 開始 preview、經過四輪修改,在 Java 25 正式定案。寫一個可以直接執行的 Java 檔案不再需要宣告 class、不需要 public static void main(String[] args)

// Hello.java — 存檔後 java Hello.java 直接執行
void main() {
    IO.println("Hello Java 25");
}

這個改動的目標受眾是兩種人:剛學 Java 的初學者(不用在第一堂課解釋五個關鍵字),以及需要快速寫一次性 script 的開發者。對已經在寫生產程式碼的人來說,既有的 public static void main 繼續能用,不影響。

另外新增了 java.lang.IO 類別,提供 IO.println()IO.print()IO.readln() 等方法。因為在 java.lang 套件下,不需要額外 import 就能使用。如果想省略 IO. 前綴,可以加上 import static java.lang.IO.*

Flexible Constructor Bodies(JEP 513)

Java 長久以來的限制:建構子的第一行必須是 super()this(),不能在呼叫父類別建構子之前做任何事。這在需要驗證參數或預處理資料時非常不方便,常常要繞道用 static helper method。

Java 25 開始,建構子可以在 super() 之前執行陳述式,只要不存取 this(因為物件還沒完全初始化):

class PositiveAmount extends Amount {
    PositiveAmount(int value) {
        // 在 super() 之前驗證參數,不合法直接擋掉
        if (value <= 0) {
            throw new IllegalArgumentException("必須為正數: " + value);
        }
        super(value);  // 驗證通過才呼叫父類別建構子
    }
}

之前要做到同樣的事,得寫成 super(validate(value)) 再另外寫一個 private static int validate(int value)。現在直接在建構子裡寫條件判斷就好,可讀性好很多。

Scoped Values(JEP 506)

Scoped Values 從 Java 20 開始孵化,在 Java 25 正式定案,定位是 ThreadLocal 的現代替代方案。

ThreadLocal 的問題大家都遇過:值設了忘記清、跨執行緒傳遞要手動處理、跟 virtual threads 搭配時每個 virtual thread 都要一份複本造成記憶體浪費。ScopedValue 用明確的作用域解決這些問題——值只在指定的範圍內可見,範圍結束自動清除,而且是不可變的:

// 宣告一個 ScopedValue,通常是 static final
static final ScopedValue<String> CURRENT_USER = ScopedValue.newInstance();

void handleRequest(String userId) {
    // 在這個 scope 裡 CURRENT_USER 的值是 userId
    ScopedValue.where(CURRENT_USER, userId).run(() -> {
        processOrder();   // 這裡面可以讀到 CURRENT_USER
        sendNotification(); // 這裡面也可以
    });
    // scope 結束,值自動清除,不會洩漏
}

void processOrder() {
    String user = CURRENT_USER.get();  // 讀取目前 scope 的值
    // ...
}

ThreadLocal 比,ScopedValue 是不可變的(同一個 scope 內不能改值),生命週期由 scope 控制(不會忘記 remove),而且在 virtual threads 之間可以透過 structured concurrency 自然繼承,不需要額外設定。如果目前的程式碼裡有 ThreadLocal 在做「傳遞 request context」這類事,值得考慮遷移。

Module Import Declarations(JEP 511)

在 Java 25 之前,要用到 java.util.Listjava.util.Mapjava.util.stream.Collectors 得一行一行 import,或用 import java.util.* 但又不包含子套件。Module Import Declarations 讓開發者一次匯入整個模組的所有公開型別:

// 匯入 java.base 模組的所有公開套件
import module java.base;

// 現在 List、Map、Stream、Path、Files 等都可以直接用
var list = List.of(1, 2, 3);
var path = Path.of("/tmp/test.txt");
var content = Files.readString(path);

搭配 JEP 512 的 compact source files 一起用的時候效果更明顯——寫一個快速 script 不用管 import 清單,import module java.base 一行搞定。在正式專案裡要不要用就看團隊偏好了,畢竟 IDE 的自動 import 已經很方便。

Compact Object Headers(JEP 519)

每個 Java 物件在 heap 上都有一段 header(存放 class 指標、hash code、GC 資訊、鎖狀態)。傳統上這段 header 佔 96 到 128 bit(12-16 bytes)。JEP 519 把它壓縮到 64 bit(8 bytes),讓整個 heap 的記憶體使用量降低。

Java 24 時這還是實驗性功能,Java 25 正式升級為產品功能,需要加 -XX:+UseCompactObjectHeaders 啟用(不再需要 -XX:+UnlockExperimentalVMOptions)。對物件密集的應用程式(大量小物件、大型集合)可以節省 10-20% 的 heap 使用量。到了 Java 27 這會成為預設行為,不需要手動開啟。

其他正式定案的 JEP

  • JEP 510 Key Derivation Function API:標準化的金鑰衍生函數 API,支援 HKDF 等演算法
  • JEP 521 Generational Shenandoah:Shenandoah GC 加入分代回收,降低暫停時間

Java 26 — 非 LTS 但有實用功能

Java 26 在 2026 年 3 月 17 日發佈,共 10 個 JEP,5 個正式定案。非 LTS 版本只有六個月的安全更新,生產環境通常不會直接用,但裡面有幾個功能值得先了解,因為後續版本會繼續帶著。

HTTP/3 支援(JEP 517)

Java 11 標準化的 HttpClient 終於支援 HTTP/3 與 QUIC 協定。預設仍然使用 HTTP/2,要用 HTTP/3 需要在建立 HttpClient 時明確指定。如果伺服器不支援 HTTP/3,會自動退回 HTTP/2 或 HTTP/1.1:

// 建立 HttpClient 時指定偏好 HTTP/3
var client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_3)
    .build();

var request = HttpRequest.newBuilder()
    .uri(URI.create("https://example.com"))
    .build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.version());  // HTTP_3 或退回 HTTP_2

HTTP/3 用 UDP 上面跑 QUIC,連線建立比 TCP+TLS 更快,重新連線時甚至可以做到 0-RTT。也不會像 TCP 那樣一個封包掉了就卡住整條線(head-of-line blocking)。對需要呼叫大量外部 API 的微服務來說,延遲改善會比較明顯。

Final 真的是 Final(JEP 500)

JEP 500 的標題 "Prepare to Make Final Mean Final" 針對的是 final 欄位。目前的 Java 雖然有 final 修飾詞保護欄位不可變,但透過 deep reflection(setAccessible(true))還是可以繞過去修改 final 欄位的值。

Java 26 開始會對這類修改行為發出執行期警告,預計未來版本會直接禁止。影響較大的是序列化框架、DI 框架、mocking 工具等會用 reflection 改 final 欄位的函式庫,升級前需要先確認相容性。

移除 Applet API(JEP 504)

Java Applet 從 Java 9 開始被標記 deprecated,在 Java 17 被標記為 forRemoval,Java 26 正式移除。java.applet 套件和所有相關的 class 都不存在了。如果有非常老的程式碼還在 import java.applet.Applet,這是升級前必須處理的 breaking change。

AOT Object Caching(JEP 516)

這是 Project Leyden 持續推進的成果。Java 24 引入的 AOT class loading 讓啟動時不用重新載入和驗證所有 class,Java 26 更進一步,允許在不同 GC 之間共用 AOT 快取的物件。對容器化部署和 serverless 場景,啟動速度的改善是實實在在的。

Java 27 — 九月即將發佈

Java 27 預計 2026 年 9 月 14 日發佈,目前處於 Rampdown Phase Two,特性已凍結。共 9 個 JEP,4 個正式定案。跟 Java 25 和 26 一樣是非 LTS,下一個 LTS 是 Java 29(預計 2027 年 9 月)。

Compact Object Headers 成為預設(JEP 534)

Java 25 引入的 Compact Object Headers 在 Java 27 預設啟用。升級到 Java 27 後,不需要加任何 JVM 參數就能享受物件 header 壓縮帶來的記憶體節省。對物件密集的應用程式來說,不用改程式碼就能拿到效能提升。

G1 成為所有環境的預設 GC(JEP 523)

G1 從 Java 9 開始就是 server 環境(2 核心以上、2 GB 以上記憶體)的預設 GC,但在資源較少的環境會退回 Serial GC。JEP 523 統一讓 G1 成為所有環境的預設值。加上 Java 26 的 G1 同步優化(JEP 522),G1 的整體表現在這兩個版本明顯提升。

Post-Quantum Hybrid Key Exchange(JEP 527)

隨著量子電腦的發展,現有的 TLS 加密金鑰交換演算法未來可能被量子攻擊破解。JEP 527 在 TLS 1.3 的握手過程中加入 hybrid key exchange,同時使用傳統演算法(如 X25519)和後量子演算法(如 ML-KEM),確保即使其中一個被破解,連線仍然安全。

這個功能對開發者來說是透明的,不需要改程式碼,JVM 會在 TLS 握手時自動使用 hybrid 模式(如果對方也支援)。主要影響是合規需求:某些政府或金融機構已經開始要求 post-quantum ready 的 TLS 實作。

JFR In-Process Data Redaction(JEP 536)

Java Flight Recorder 新增資料脫敏功能,可以在事件寫入前遮蔽敏感資訊(如資料庫連線字串裡的密碼、HTTP header 中的 token)。對需要在生產環境持續收集 JFR 資料但又擔心敏感資訊外洩的團隊來說,這解決了實際痛點。

一直停在 Preview 的功能

Java 的 preview 機制讓新功能可以先讓開發者試用、收集回饋後再正式定案。大部分功能經過 2-3 輪 preview 就會定案,但有幾個功能已經在 preview 階段待了非常久:

功能首次 PreviewJava 27 狀態輪數
Vector APIJava 16(2021 Incubator)12th Incubator12
Structured ConcurrencyJava 19(2022 Incubator)7th Preview9(含 2 輪 Incubator)
Primitive Types in PatternsJava 23(2024)5th Preview5
PEM EncodingsJava 25(2025)3rd Preview3

Vector API 從 Java 16 開始孵化,到 Java 27 已經是第 12 輪 incubator,是 Java 歷史上最「長壽」的孵化功能。這不完全是因為 API 設計有問題,而是它依賴 Project Valhalla 的 value types(讓 vector 操作能直接用 CPU SIMD 指令而不經過 boxing),而 Valhalla 本身進度就很慢。

Structured Concurrency 的情況不太一樣。API 設計在多輪迭代中一直在調整——scope 的建立方式、子任務的錯誤處理策略、跟 Scoped Values 的互動——每一輪都有不小的改動。以目前的速度,Java 29(下一個 LTS)正式定案的機會比較大,但也不確定。

對開發者來說,preview 功能在生產環境使用需要加 --enable-preview flag,而且每次升級版本都可能面臨 API 變動。如果不是真的需要、或者有其他替代方案(例如用 ExecutorService 搭配 virtual threads 取代 structured concurrency),建議等正式定案再用。

版本對照表

三個版本的完整 JEP 狀態:

JEP功能Java 25Java 26Java 27
506Scoped ValuesFinal
510Key Derivation Function APIFinal
511Module Import DeclarationsFinal
512Compact Source FilesFinal
513Flexible Constructor BodiesFinal
519Compact Object HeadersProduct534 Default
521Generational ShenandoahFinal
500Final Mean FinalFinal
504Remove Applet APIFinal
516AOT Object CachingFinal
517HTTP/3 for HttpClientFinal
522G1 Throughput ImprovementFinal
523G1 Default for AllFinal
527Post-Quantum TLSFinal
536JFR Data RedactionFinal

升級建議

如果目前還在 Java 21,升級到 Java 25 是合理的下一步——同為 LTS,各家 JDK 發行版的支援時間都拉到 2030 年以後。Java 25 帶來的 Compact Object Headers(手動開啟)、Scoped Values、Flexible Constructor Bodies 都不會造成 breaking change,升級門檻不高。

Java 26 和 27 是非 LTS,生產環境不建議直接用,但可以在開發環境先試。特別是 Java 27 的 Compact Object Headers 預設開啟,可以提前測試應用程式在新 header 格式下有沒有相容性問題(某些依賴物件 header layout 的第三方工具可能受影響)。

至於下一個 LTS Java 29(預計 2027 年 9 月),會收編 Java 26 和 27 的所有正式功能,包括 HTTP/3、G1 全面預設、Compact Object Headers 預設、Post-Quantum TLS。如果不急著用這些功能,等 Java 29 也是一個選擇。各家 JDK 發行版的支援時間可以看 OpenJDK 發行版整理Java 版本演進 兩篇。


Sponsored Links