Java 9 於 2017 年 9 月發布,是 Java 8 後首個重大版本,引入模塊系統徹底重塑 JDK 結構,並帶來 REPL、HTTP/2、進程 API、多版本 JAR 等開發體驗與效能雙重提升的特性。本文系統梳理 9 大核心特性與遷移指南。
核心目標:解決 JAR 地獄、封裝內部 API、縮減運行時體積、啟用編譯期模塊邊界檢查。
module com.example.myapp {
requires java.sql; // 依賴模塊
requires transitive java.logging; // 可傳遞依賴
exports com.example.api; // 導出包
opens com.example.impl to com.example.test; // 反射開放
uses com.example.spi.Service; // 使用服務
provides com.example.spi.Service with com.example.impl.ServiceImpl; // 提供實現
}
java.base 等 90+ 模塊jlink --module-path $JAVA_HOME/jmods --add-modules java.base,java.logging --output my-jre 生成 30MB+ 精簡 JREMETA-INF/versions/9/$ jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell> String greeting = "Hello JShell"
greeting ==> "Hello JShell"
jshell> System.out.println(greeting)
Hello JShell
jshell> /list
1 : String greeting = "Hello JShell"
2 : System.out.println(greeting)
jshell> /save demo.jsh
jshell> /exit
優勢:即時驗證 API、學習語法、原型開發、教學演示,無需建項目、寫 main、編譯運行。
// Java 9: jdk.incubator.httpclient
// Java 11+: java.net.http (標準化)
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com/users/octocat"))
.header("Accept", "application/vnd.github.v3+json")
.GET()
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode()); // 200
System.out.println(response.body()); // JSON 響應
// 異步非阻塞
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
特性:HTTP/2 多路複用、Header 壓縮 (HPACK)、Server Push、WebSocket 原生支援、異步 CompletableFuture、響應式流 (BodyHandlers.ofPublisher())。
// 獲取當前進程 PID (跨平台)
long pid = ProcessHandle.current().pid();
System.out.println("PID: " + pid);
// 列舉所有進程
ProcessHandle.allProcesses()
.filter(p -> p.info().command().orElse("").contains("java"))
.forEach(p -> System.out.println(p.pid() + " " + p.info().command()));
// 獲取進程信息
ProcessHandle.Info info = ProcessHandle.current().info();
info.command().ifPresent(System.out::println); // 命令
info.arguments().ifPresent(args -> System.out.println(Arrays.toString(args))); // 參數
info.startInstant().ifPresent(System.out::println); // 啟動時間
info.totalCpuDuration().ifPresent(System.out::println); // CPU 時間
info.user().ifPresent(System.out::println); // 用戶
終結 Runtime.exec("ps -ef") 等平台相關 Hack,統一跨平台 API。
標準化 JSON 處理,無需三方庫 (Jackson/Gson) 即可完成基礎解析生成:
import javax.json.*;
JsonObject obj = Json.createObjectBuilder()
.add("name", "Java 9")
.add("features", Json.createArrayBuilder()
.add("Modules").add("JShell").add("HTTP/2"))
.build();
try (JsonWriter writer = Json.createWriter(System.out)) {
writer.writeObject(obj); // 格式化輸出
}
// 解析
JsonReader reader = Json.createReader(new StringReader(jsonString));
JsonObject parsed = reader.readObject();
String name = parsed.getString("name");
import javax.money.*;
MonetaryAmount amt1 = Money.of(1234.56, "USD");
MonetaryAmount amt2 = Money.of(789.01, "EUR");
// 貨幣轉換 (需匯率提供者)
ExchangeRateProvider provider = MonetaryConversions.getExchangeRateProvider("ECB");
CurrencyConversion conversion = provider.getCurrencyConversion("EUR");
MonetaryAmount converted = amt1.with(conversion); // USD -> EUR
// 格式化
MonetaryAmountFormat fmt = MonetaryFormats.getAmountFormat(Locale.GERMANY);
System.out.println(fmt.format(amt1)); // 1.234,56 USD
synchronized、ReentrantLock 在高爭用下的性能javac 成為默認編譯器| 特性 | 狀態 | 最終交付版本 |
|---|---|---|
| HTTP/2 客戶端標準化 | Incubator → 標準 | Java 11 (JEP 321) |
| Var 類型推斷 | JEP 286 | Java 10 |
| Switch 表達式 | JEP 325/354 | Java 12/13/14 |
| Record 類型 | JEP 359/384/395 | Java 14/15/16 |
| 模式匹配 | JEP 305/375/394 | Java 14/16/17 |
| 密封類 | JEP 360/397/409 | Java 15/16/17 |
--add-modules java.xml.bind,java.activation 解決 JAXB 等移除模塊--add-opens java.base/java.lang=ALL-UNNAMED 臨時開放反射jhat, jjs (Nashorn 後移除), appletviewer 等Java 9 開啟六個月發布節奏 (3月/9月),LTS 版本每 3 年 (Java 8, 11, 17, 21...)。非 LTS 版本僅 6 個月支持,生產環境強烈建議鎖定 LTS。