Java14的新特性

Java語言特性系列

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

版本號

java -version
openjdk version "14" 2020-03-17
OpenJDK Runtime Environment (build 14+36-1461)
OpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)
從version信息能夠看出是build 14+36

特性列表

305:Pattern Matching for instanceof (Preview)

JDK14引入了preview版本的針對instanceof的模式匹配,其用法示例以下
public boolean isBadRequestError(Exception ex) {
        return (ex instanceof HttpClientErrorException rce) &&
                HttpStatus.BAD_REQUEST == rce.getStatusCode();
    }
無需在本身進行類型強轉

343:Packaging Tool (Incubator)

JDK14引入了jdk.incubator.jpackage.jmod,它基於JavaFX javapackager tool構建,目的在於建立一個簡單的打包工具,能夠用於構建exe、pkg、dmg、deb、rpm格式的安裝文件;非模塊化的app的構建示例以下
jpackage --name myapp --input lib --main-jar main.jar

345:NUMA-Aware Memory Allocation for G1

實現了NUMA-aware的內存分配,以提高G1在大型機器上的性能

349:JFR Event Streaming

JDK11引入了JFR,使用的時候先dump到磁盤上而後再分析;而在JDK14則支持stream方式來進行持續性的監控,示例以下
public class AgentMain implements Runnable {

    public static void premain(String agentArgs, Instrumentation inst) {
        try {
            Logger.getLogger("AgentMain").log(
                    Level.INFO, "Attaching JFR Monitor");
            new Thread(new AgentMain()).start();
        } catch (Throwable t) {
            Logger.getLogger("AgentMain").log(
                    Level.SEVERE,"Unable to attach JFR Monitor", t);
        }
    }

    @Override
    public void run() {
        var sender = new JfrStreamEventSender();
        try (var rs = new RecordingStream()) {
            rs.enable("jdk.CPULoad")
                    .withPeriod(Duration.ofSeconds(1));
            rs.enable("jdk.JavaMonitorEnter")
                    .withThreshold(Duration.ofMillis(10));
            rs.onEvent("jdk.CPULoad", sender);
            rs.onEvent("jdk.JavaMonitorEnter", sender);
            rs.start();
        }
    }
}

352:Non-Volatile Mapped Byte Buffers

該特性新增了java.base/jdk/internal/misc/ExtendedMapMode.java以支持MappedByteBuffer訪問non-volatile memory (NVM)

358:Helpful NullPointerExceptions

該特性能夠更好地提示哪一個地方出現的空指針,須要經過-XX:+ShowCodeDetailsInExceptionMessages開啓,示例以下
public class NullPointerExample {

    public record City(String name){

    }

    public record Location(City city) {

    }

    public record User(String name, Location location) {

    }

    public static void main(String[] args){
        User user = new User("hello", new Location(null));
        System.out.println(user.location().city().name());
    }
}
輸出以下
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.example.NullPointerExample$City.name()" because the return value of "com.example.NullPointerExample$Location.city()" is null
    at com.example.NullPointerExample.main(NullPointerExample.java:25)

359:Records (Preview)

JDK14引入了preview版本的record類型,示例以下
public record Point(int x, int y) {

    public Point {
        System.out.println(String.format("(%d,%d)", x, y));
    }

    public Point(int value) {
        this(value, value);
    }

    public static Point of(int value) {
        return new Point(value, value);
    }
}
javap反編譯以下
javac --enable-preview -source 14 Point.java
javap -verbose Point.class
Compiled from "Point.java"
public final class com.example.domain.Point extends java.lang.Record {
  public com.example.domain.Point(int, int);
  public static com.example.domain.Point of(int);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public int x();
  public int y();
}
能夠看見Point繼承了java.lang.Record,並且經過invokedynamic提供了final的hashCode及equals

361:Switch Expressions (Standard)

JDK12引入的switch在JDK14變爲正式版本,正式版主要是用 ->來替代之前的 :+ break;另外就是提供了yield來在block中返回值,示例以下
public void testSwitchWithArrowBlockAndYield() {
        int n = 3;
        String quantityString = switch (n) {
            case 1 -> "one";
            case 2 -> "two";
            default -> {
                System.out.println("default");
                yield "many";
            }
        };
        System.out.println(quantityString);
    }

362:Deprecate the Solaris and SPARC Ports

廢棄了 Solaris/SPARC, Solaris/x64, and Linux/SPARC ports,以在將來的版本中移除

363:Remove the Concurrent Mark Sweep (CMS) Garbage Collector

移除了CMS垃圾收集器,若是在JDK14中使用-XX:+UseConcMarkSweepGC的話,會出現warning,可是不會exit而是以默認的垃圾收集器運行,以下
OpenJDK 64-Bit Server VM warning: Ignoring option UseConcMarkSweepGC; support was removed in 14.0

364:ZGC on macOS

以前的ZGC只能在linux上使用,如今mac上也能使用ZGC了,示例以下
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

365:ZGC on Windows

以前的ZGC只能在linux上使用,如今windows( 不能低於1803版本)上也能使用ZGC了,示例以下
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

366:Deprecate the ParallelScavenge + SerialOld GC Combination

廢棄了parallel young generation GC與SerialOld GC的組合( -XX:+UseParallelGC與-XX:-UseParallelOldGC配合開啓),如今使用-XX:+UseParallelGC -XX:-UseParallelOldGC或者-XX:-UseParallelOldGC都會出現告警以下
OpenJDK 64-Bit Server VM warning: Option UseParallelOldGC was deprecated in version 14.0 and will likely be removed in a future release.
單獨使用-XX:+UseParallelGC則開啓parallel young and old generation GC algorithms

367:Remove the Pack200 Tools and API

移除了Pack200 API

368:Text Blocks (Second Preview)

JDK13引入的text blocks進行第二輪preview,JDK14的版本主要增長了兩個escape sequences,分別是 \<line-terminator>\s escape sequence,示例以下
@Test
    public void testTextBlockWithTwoNewEscapeSequences() {
        String inOneLine = """
                Lorem ipsum dolor sit amet, consectetur adipiscing \
                elit, sed do eiusmod tempor incididunt ut labore \
                et dolore magna aliqua.\
                """;
        System.out.println(inOneLine);

        String singleSpace = """
                red  \s
                green\s
                blue \s
                """;
        System.out.println(singleSpace);
    }

370:Foreign-Memory Access API (Incubator)

提供了incubator版本的API用於操縱堆外內存,使用示例以下
@Test
    public void testForeignMemoryAccessAPI() {
        SequenceLayout intArrayLayout
                = MemoryLayout.ofSequence(25,
                MemoryLayout.ofValueBits(32,
                        ByteOrder.nativeOrder()));

        VarHandle intElemHandle
                = intArrayLayout.varHandle(int.class,
                MemoryLayout.PathElement.sequenceElement());

        try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) {
            MemoryAddress base = segment.baseAddress();
            for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++) {
                intElemHandle.set(base, (long) i, i);
            }
        }
    }

細項解讀

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

添加項

  • New Method to SAX ContentHandler for Handling XML Declaration (JDK-8230814)
給SAX ContentHandler新增了方法,以下
default void declaration(String version, String encoding, String standalone)
        throws SAXException
    {
        //no op
    }

移除項

  • Removal of sun.nio.cs.map System Property (JDK-8229960)
移除了sun.nio.cs.map屬性
  • Removed Deprecated java.security.acl APIs (JDK-8191138)
移除了java.security.acl
  • Removal of the Default keytool -keyalg Value (JDK-8214024)
移除了默認的keytool -keyalg

廢棄項

  • Thread Suspend/Resume Are Deprecated for Removal (JDK-8231602)
廢棄了Thread的以下方法
Thread.suspend()
Thread.resume()
ThreadGroup.suspend()
ThreadGroup.resume()
ThreadGroup.allowThreadSuspension(boolean)

已知問題

  • Text Visibility Issues in macOS Dark Mode (JDK-8228555)
已知在macOS上的Dark Mode有Text Visibility Issues

其餘事項

  • Thread.countStackFrames Changed to Unconditionally Throw UnsupportedOperationException (JDK-8205132)
Thread.countStackFrames開啓轉爲無條件地拋出UnsupportedOperationException

小結

Java14主要有以下幾個特性linux

doc

相關文章
相關標籤/搜索