Java18的新特性

codecraft發表於2022-03-24
Java語言特性系列

本文主要講述一下Java18的新特性

版本號

java -version
openjdk version "18" 2022-03-22
OpenJDK Runtime Environment (build 18+36-2087)
OpenJDK 64-Bit Server VM (build 18+36-2087, mixed mode, sharing)
從version資訊可以看出是build 18+36

特性列表

JEP 400: UTF-8 by Default

java18以前Charset.defaultCharset()是根據作業系統、user locale等來決定的,導致不同作業系統的預設charset是不一樣,這次統一改為了UTF-8
java18要統一為UTF-8則需要-Dfile.encoding=UTF-8來設定
如果還想沿用以前的判斷方式則可以通過-Dfile.encoding=COMPAT來設定

JEP 408: Simple Web Server

提供了一個類似python的SimpleHTTPServer(python -m SimpleHTTPServer [port])的開箱即用的HTTP檔案伺服器
可以通過jwebserver -p 9000啟動
jwebserver -p 9000
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /tmp and subdirectories on 127.0.0.1 port 9000
URL http://127.0.0.1:9000/
也可以在程式碼裡定製並啟動
jshell> var server = SimpleFileServer.createFileServer(new InetSocketAddress(8080),
   ...> Path.of("/some/path"), OutputLevel.VERBOSE);
jshell> server.start()

JEP 413: Code Snippets in Java API Documentation

以前要在通過javadoc展示程式碼可以使用@code如下
<pre>{@code
    lines of source code
}</pre>

但是它的缺點就是得用pre包裝,導致該片段不能包含html標籤,而且縮排不太靈活

而這次給javaDoc引入了@snippet標籤,無需對html標籤再進行轉義

/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet :
 * if (v.isPresent()) {
 *     System.out.println("v: " + v.get());
 * }
 * }
 */
也可以直接引用原始碼,避免javadoc的程式碼與實際程式碼脫節
/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet file="ShowOptional.java" region="example"}
 */

JEP 416: Reimplement Core Reflection with Method Handles

通過Method Handles重新實現java.lang.reflect.Method, Constructor及Field來替代位元組碼生成的Method::invoke, Constructor::newInstance, Field::get, and Field::set的實現
方便支援Project Valhalla,為以後減少擴充套件成本

JEP 417: Vector API (Third Incubator)

JDK16引入了JEP 338: Vector API (Incubator)提供了jdk.incubator.vector來用於向量計算
JDK17進行改進並作為第二輪的incubatorJEP 414: Vector API (Second Incubator)
JDK18進行改進並作為第三輪的incubator

JEP 418: Internet-Address Resolution SPI

給解析網路地址提供了SPI,即java.net.spi包的InetAddressResolverProvider
方便給project loom做準備(目前InetAddress的API會阻塞在系統呼叫),也方便定製化及testing

JEP 419: Foreign Function & Memory API (Second Incubator)

JDK14的JEP 370: Foreign-Memory Access API (Incubator)引入了Foreign-Memory Access API作為incubator
JDK15的JEP 383: Foreign-Memory Access API (Second Incubator)Foreign-Memory Access API作為第二輪incubator
JDK16的JEP 393: Foreign-Memory Access API (Third Incubator)作為第三輪,它引入了Foreign Linker API
JDK17引入JEP 412: Foreign Function & Memory API (Incubator)作為第一輪incubator
JDK18則作為第二輪的incubator

JEP 420: Pattern Matching for switch (Second Preview)

instanceof的模式匹配在JDK14作為preview,在JDK15作為第二輪的preview,在JDK16轉正
static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}
JDK17引入JEP 406: Pattern Matching for switch (Preview)
JDK18則作為第二輪的preview

JEP 421: Deprecate Finalization for Removal

廢棄finalize方法方便後續移除

細項解讀

上面列出的是大方面的特性,除此之外還有一些api的更新及廢棄,主要見JDK 18 Release Notes,這裡舉幾個例子。

新增項

  • SerialGC、ParallelGC、ZGC支援String Deduplication

    可使用-XX:+UseStringDeduplication開啟
  • Map from an Element to its JavaFileObject

    新增Elements.getFileObjectOf(Element)來對映為JavaFileObject
  • Configurable Card Table Card SizeJDK-8272773

    可以使用-XX:GCCardSizeInBytes來設定card table大小
  • Allow G1 Heap Regions up to 512MBJDK-8275056

    允許G1的heap regions的最大值從之前的32MB到512MB
  • JDK Flight Recorder Event for FinalizationJDK-8266936

    新增jdk.FinalizerStatistics

移除項

  • Removal of Google's GlobalSign Root CertificateJDK-8225083

    移除了google的GlobalSign根證照
  • Removal of Empty finalize() Methods in java.desktop ModuleJDK-8273102

    移除java.desktop模組裡頭的空finalize()方法
  • Removal of impl.prefix JDK System Property Usage From InetAddressJDK-8274227

    移除impl.prefix屬性,轉而使用InetAddressResolver這個spi
  • Removal of Support for Pre JDK 1.4 DatagramSocketImpl ImplementationsJDK-8260428

    移除jdk1.4之前的DatagramSocketImpl
  • Removal of Legacy PlainSocketImpl and PlainDatagramSocketImpl ImplementationsJDK-8253119

    移除java.net.SocketImpl及java.net.DatagramSocketImpl的老實現PlainSocketImpl、PlainDatagramSocketImpl
    jdk.net.usePlainDatagramSocketImpl屬性也一併移除

廢棄項

完整列表見deprecated-list

  • Deprecated Subject::doAs for RemovalJDK-8267108

    廢棄javax.security.auth.Subject::doAs為移除做準備
  • Deprecated sun.misc.Unsafe Methods That Return OffsetsJDK-8277863

    sun.misc.Unsafe中objectFieldOffset, staticFieldOffset, staticFieldBase方法被廢棄
  • Terminally Deprecated Thread.stopJDK-8277861

    廢棄Thread.stop為後續移除做準備
  • Obsoleted Product Options -XX:G1RSetRegionEntries and -XX:G1RSetSparseRegionEntriesJDK-8017163

    廢棄-XX:G1RSetRegionEntries-XX:G1RSetSparseRegionEntries

已知問題

  • Extended Delay Before JDK Executable Installer Starts From Network DriveJDK-8274002

    在 Windows 11 和 Windows Server 2022 上,從對映的網路驅動器啟動時,臨時安裝檔案的提取可能會有些緩慢。安裝程式仍然可以工作,但可能會有暫時的延遲。

小結

Java18主要有如下幾個特性

doc