Java13的新特性

Java語言特性系列

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

版本號

java -version
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment (build 13+33)
OpenJDK 64-Bit Server VM (build 13+33, mixed mode, sharing)
從version信息能夠看出是build 13+33

特性列表

350: Dynamic CDS Archives

JDK5引入了Class-Data Sharing能夠用於多個JVM共享class,提高啓動速度,最先只支持system classes及serial GC
JDK9對其進行擴展以支持application classes及其餘GC算法
java10的新特性 JEP 310: Application Class-Data Sharing擴展了JDK5引入的Class-Data Sharing,支持application的Class-Data Sharing並開源出來(之前是commercial feature)
JDK11將-Xshare:off改成默認-Xshare:auto,以更加方便使用CDS特性
JDK12的 341: Default CDS Archives即在64-bit平臺上編譯jdk的時候就默認在${JAVA_HOME}/lib/server目錄下生成一份名爲classes.jsa的默認archive文件(大概有18M)方便你們使用
JDK13的這個特性支持在Java application執行以後進行動態archive
  • 導出jsa
java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
  • 使用jsa
java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

351: ZGC: Uncommit Unused Memory

Java12的 346: Promptly Return Unused Committed Memory from G1新增了兩個參數分別是G1PeriodicGCInterval及G1PeriodicGCSystemLoadThreshold用於GC以後從新調整Java heap size,而後將多餘的內存歸還給操做系統
Java12的 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)擁有參數-XX:ShenandoahUncommitDelay=<milliseconds>來指定ZPage的page cache的失效時間,而後歸還內存
Java13則給ZGC新增歸還unused heap memory給操做系統的特性;它新增了幾個參數,-XX:ZUncommitDelay=<seconds>用於指定ZPage的page cache的失效時間;ZGC的歸還內存默認是開啓的,可使用-XX:-ZUncommit來顯式禁用

353: Reimplement the Legacy Socket API

本特性替換了java.net.Socket以及java.net.ServerSocket API的底層實現;它使用NioSocketImpl來替換JDK1.0的PlainSocketImpl;若是要繼續使用舊版的Socket實現,可使用-Djdk.net.usePlainSocketImpl參數來切換到舊版本

/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/lib/src.zip!/java.base/java/net/SocketImpl.javajava

public abstract class SocketImpl implements SocketOptions {
    private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl();

    private static boolean usePlainSocketImpl() {
        PrivilegedAction<String> pa = () -> NetProperties.get("jdk.net.usePlainSocketImpl");
        String s = AccessController.doPrivileged(pa);
        return (s != null) && !s.equalsIgnoreCase("false");
    }

    /**
     * Creates an instance of platform's SocketImpl
     */
    @SuppressWarnings("unchecked")
    static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
        if (USE_PLAINSOCKETIMPL) {
            return (S) new PlainSocketImpl(server);
        } else {
            return (S) new NioSocketImpl(server);
        }
    }

    //......
}
SocketImpl的USE_PLAINSOCKETIMPL取決於usePlainSocketImpl方法,而它會從NetProperties讀取dk.net.usePlainSocketImpl配置,若是不爲null且不爲false,則usePlainSocketImpl方法返回true;createPlatformSocketImpl會根據USE_PLAINSOCKETIMPL來建立PlainSocketImpl或者NioSocketImpl

354: Switch Expressions (Preview)

本特性主要是使用yield替換了break來避免歧義,由於break能夠用來進行跳轉執行相似goto的操做
@Test
    public void testSwitchYield(){
        String dayOfWeek = switch(1){
            case 1 -> {
                String day = "Monday";
                yield day;
            }
            case 2 -> {
                String day = "Tuesday";
                yield day;
            }
            default -> "Unknown";
        };
        System.out.println(dayOfWeek);
    }

355: Text Blocks (Preview)

本特性主要引入了Text Blocks,使用"""來包圍一段text block,能夠內置佔位符最後使用String.format來填充
@Test
    public void testTextBlock(){
        // Without Text Blocks
        String html = "<html>\n" +
                "   <body>\n" +
                "      <p>Hello, Escapes</p>\n" +
                "   </body>\n" +
                "</html>\n";
        System.out.println(html);

        // With Text Blocks
        String html2 = """
            <html>
                <body>
                <p>Hello, %s</p>
                </body>
            </html>""";

        System.out.println(String.format(html2, "World"));

        String htmlWithNewLine = """
            <html>
                <body>
                <p>Hello World</p>
                </body>
            </html>
            """;
        System.out.print(htmlWithNewLine);
        System.out.println("a new line");
    }
須要注意text blocks不能在一行,另外若是結尾的"""在新的一行則會輸出新的一行

細項解讀

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

添加項

  • 添加FileSystems.newFileSystem(Path, Map<String, ?>) Method
  • 新的java.nio.ByteBuffer Bulk get/put Methods Transfer Bytes Without Regard to Buffer Position
  • 支持Unicode 12.1
  • 添加-XX:SoftMaxHeapSize Flag,目前僅僅對ZGC起做用
  • ZGC的最大heap大小增大到16TB

移除項

  • 移除awt.toolkit System Property
  • 移除Runtime Trace Methods
  • 移除-XX:+AggressiveOpts
  • 移除Two Comodo Root CA Certificates、Two DocuSign Root CA Certificates
  • 移除內部的com.sun.net.ssl包

廢棄項

  • 廢棄-Xverify:none及-noverify
  • 廢棄rmic Tool並準備移除
  • 廢棄javax.security.cert並準備移除

已知問題

  • 再也不支持Windows 2019 Core Server
  • 使用ZIP File System (zipfs) Provider來更新包含Uncompressed Entries的ZIP或JAR可能形成文件損壞

其餘事項

  • GraphicsEnvironment.getCenterPoint()及getMaximumWindowBounds()已跨平臺統一
  • 加強了JAR Manifest的Class-Path屬性處理
jdk.net.URLClassPath.showIgnoredClassPathEntries屬性設置爲true能夠用來幫助查看非法的Class-Path entries
  • 針對Negatively Sized Argument,StringBuffer(CharSequence)及StringBuilder(CharSequence)會拋出NegativeArraySizeException
  • linux的默認進程啓動機制已經使用posix_spawn
  • Lookup.unreflectSetter(Field)針對static final fields會拋出IllegalAccessException
  • 使用了java.net.Socket.setSocketImplFactory及java.net.ServerSocket.setSocketFactory方法的要注意,要求客戶端及服務端要一致,不能一端使用自定義的factory一端使用默認的factory
  • SocketImpl的supportedOptions, getOption及setOption方法的默認實現發生了變化,默認的supportedOptions返回空,而默認的getOption,及setOption方法拋出UnsupportedOperationException
  • JNI NewDirectByteBuffer建立的Direct Buffer爲java.nio.ByteOrder.BIG_ENDIAN
  • Base64.Encoder及Base64.Decoder可能拋出OutOfMemoryError
  • 改進了Serial GC Young pause time report
  • 改進了MaxRAM及UseCompressedOops參數的行爲

小結

  • Java13主要新增了以下特性算法

    • 350: Dynamic CDS Archives
    • 351: ZGC: Uncommit Unused Memory
    • 353: Reimplement the Legacy Socket API
    • 354: Switch Expressions (Preview)
    • 355: Text Blocks (Preview)
  • 語法層面,改進了Switch Expressions,新增了Text Blocks,兩者皆處於Preview狀態;API層面主要使用NioSocketImpl來替換JDK1.0的PlainSocketImpl
  • GC層面則改進了ZGC,以支持Uncommit Unused Memory

doc

相關文章
相關標籤/搜索