Java12的新特性

Java語言特性系列

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

版本號

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

特性列表

Shenandoah GC是一個面向low-pause-time的垃圾收集器,它最初由Red Hat實現,支持aarch64及amd64 architecture;ZGC也是面向low-pause-time的垃圾收集器,不過ZGC是基於colored pointers來實現,而Shenandoah GC是基於brooks pointers來實現;若是要使用Shenandoah GC須要編譯時--with-jvm-features選項帶有shenandoahgc,而後啓動時使用-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
在jdk源碼裏頭新增了一套基礎的microbenchmarks suite
對switch進行了加強,除了使用statement還能夠使用expression,好比原來的寫法以下:
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}

如今能夠改成以下寫法:java

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

以及在表達式返回值算法

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};

對於須要返回值的switch expression要麼正常返回值要麼拋出異常,如下這兩種寫法都是錯誤的express

int i = switch (day) {
    case MONDAY -> {
        System.out.println("Monday"); 
        // ERROR! Block doesn't contain a break with value
    }
    default -> 1;
};
i = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY: 
        break 0;
    default: 
        System.out.println("Second half of the week");
        // ERROR! Group doesn't contain a break with value
};
新增了JVM Constants API,具體來講就是java.base模塊新增了java.lang.constant包,引入了ConstantDesc接口( ClassDesc、MethodTypeDesc、MethodHandleDesc這幾個接口直接繼承了ConstantDesc接口)以及Constable接口;ConstantDesc接口定義了resolveConstantDesc方法,Constable接口定義了describeConstable方法;String、Integer、Long、Float、Double均實現了這兩個接口,而EnumDesc實現了ConstantDesc接口
64-bit Arm platform (arm64),也能夠稱之爲aarch64;以前JDK有兩個關於aarch64的實現,分別是src/hotspot/cpu/arm以及open/src/hotspot/cpu/aarch64,它們的實現重複了,爲了集中精力更好地實現aarch64,該特性在源碼中刪除了open/src/hotspot/cpu/arm中關於64-bit的實現,保留其中32-bit的實現,因而open/src/hotspot/cpu/aarch64部分就成了64-bit ARM architecture的默認實現
java10的新特性 JEP 310: Application Class-Data Sharing擴展了JDK5引入的Class-Data Sharing,支持application的Class-Data Sharing;Class-Data Sharing能夠用於多個JVM共享class,提高啓動速度,最先只支持system classes及serial GC,JDK9對其進行擴展以支持application classes及其餘GC算法,並在JDK10中開源出來( 之前是commercial feature);JDK11將-Xshare:off改成默認-Xshare:auto,以更加方便使用CDS特性;JDK12的這個特性即在64-bit平臺上編譯jdk的時候就默認在${JAVA_HOME}/lib/server目錄下生成一份名爲classes.jsa的默認archive文件( 大概有18M)方便你們使用
G1在garbage collection的時候,一旦肯定了collection set( CSet)開始垃圾收集這個過程是without stopping的,當collection set過大的時候,此時的STW時間會過長超出目標pause time,這種狀況在mixed collections時候比較明顯。這個特性啓動了一個機制,當選擇了一個比較大的collection set,容許將其分爲mandatory及optional兩部分( 當完成mandatory的部分,若是還有剩餘時間則會去處理optional部分)來將mixed collections從without stopping變爲abortable,以更好知足指定pause time的目標
G1目前只有在full GC或者concurrent cycle的時候纔會歸還內存,因爲這兩個場景都是G1極力避免的,所以在大多數場景下可能不會及時會還committed Java heap memory給操做系統。JDK12的這個特性新增了兩個參數分別是G1PeriodicGCInterval及G1PeriodicGCSystemLoadThreshold,設置爲0的話,表示禁用。當上一次garbage collection pause過去G1PeriodicGCInterval( milliseconds)時間以後,若是getloadavg()( one-minute)低於G1PeriodicGCSystemLoadThreshold指定的閾值,則觸發full GC或者concurrent GC( 若是開啓G1PeriodicGCInvokesConcurrent),GC以後Java heap size會被重寫調整,而後多餘的內存將會歸還給操做系統

細項解讀

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

添加項

  • 支持unicode 11
  • 支持Compact Number Formatting
使用實例以下
@Test
    public void testCompactNumberFormat(){
        var cnf = NumberFormat.getCompactNumberInstance(Locale.CHINA, NumberFormat.Style.SHORT);
        System.out.println(cnf.format(1_0000));
        System.out.println(cnf.format(1_9200));
        System.out.println(cnf.format(1_000_000));
        System.out.println(cnf.format(1L << 30));
        System.out.println(cnf.format(1L << 40));
        System.out.println(cnf.format(1L << 50));
    }

輸出api

1萬
2萬
100萬
11億
1兆
1126兆
  • String支持transform、indent操做
@Test
    public void testStringTransform(){
        System.out.println("hello".transform(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.hashCode();
            }
        }));
    }

    @Test
    public void testStringIndent(){
        System.out.println("hello".indent(3));
    }
  • Files新增mismatch方法
@Test
    public void testFilesMismatch() throws IOException {
        FileWriter fileWriter = new FileWriter("/tmp/a.txt");
        fileWriter.write("a");
        fileWriter.write("b");
        fileWriter.write("c");
        fileWriter.close();

        FileWriter fileWriterB = new FileWriter("/tmp/b.txt");
        fileWriterB.write("a");
        fileWriterB.write("1");
        fileWriterB.write("c");
        fileWriterB.close();

        System.out.println(Files.mismatch(Path.of("/tmp/a.txt"),Path.of("/tmp/b.txt")));
    }
  • Collectors新增teeing方法用於聚合兩個downstream的結果
@Test
    public void testCollectorTeeing(){
        var result = Stream.of("Devoxx","Voxxed Days","Code One","Basel One")
                .collect(Collectors.teeing(Collectors.filtering(n -> n.contains("xx"),Collectors.toList()),
                                            Collectors.filtering(n -> n.endsWith("One"),Collectors.toList()),
                        (List<String> list1, List<String> list2) -> List.of(list1,list2)
                                            ));

        System.out.println(result.get(0));
        System.out.println(result.get(1));
    }
  • CompletionStage新增exceptionallyAsync、exceptionallyCompose、exceptionallyComposeAsync方法
@Test
    public void testExceptionallyAsync() throws ExecutionException, InterruptedException {
        LOGGER.info("begin");
        int result = CompletableFuture.supplyAsync(() -> {
            LOGGER.info("calculate");
            int i = 1/0;
            return 100;
        }).exceptionallyAsync((t) -> {
            LOGGER.info("error error:{}",t.getMessage());
            return 0;
        }).get();

        LOGGER.info("result:{}",result);
    }
  • JDK12以前CompletionStage只有一個exceptionally,該方法體在主線程執行,JDK12新增了exceptionallyAsync、exceptionallyComposeAsync方法容許方法體在異步線程執行,同時新增了exceptionallyCompose方法支持在exceptionally的時候構建新的CompletionStage
  • Allocation of Old Generation of Java Heap on Alternate Memory Devices
G1及Parallel GC引入experimental特性,容許將old generation分配在諸如NV-DIMM memory的alternative memory device
  • ZGC: Concurrent Class Unloading
ZGC在JDK11的時候還不支持class unloading,JDK12對ZGC支持了Concurrent Class Unloading,默認是開啓,使用-XX:-ClassUnloading能夠禁用
  • 新增-XX:+ExtensiveErrorReports
-XX:+ExtensiveErrorReports能夠用於在jvm crash的時候收集更多的報告信息到hs_err<pid>.log文件中,product builds中默認是關閉的,要開啓的話,須要本身添加-XX:+ExtensiveErrorReports參數
  • 新增安全相關的改進
支持java.security.manager系統屬性,當設置爲disallow的時候,則不使用SecurityManager以提高性能,若是此時調用System.setSecurityManager則會拋出UnsupportedOperationException
keytool新增-groupname選項容許在生成key pair的時候指定一個named group
新增PKCS12 KeyStore配置屬性用於自定義PKCS12 keystores的生成
Java Flight Recorder新增了security-related的event
支持ChaCha20 and Poly1305 TLS Cipher Suites
  • jdeps Reports Transitive Dependences
jdeps的--print-module-deps, --list-deps, 以及--list-reduce-deps選項獲得加強,新增--no-recursive用於non-transitive的依賴分析,--ignore-missing-deps用於suppress missing dependence errors

移除項

  • 移除com.sun.awt.SecurityWarnin
  • 移除FileInputStream、FileOutputStream、Java.util.ZipFile/Inflator/Deflator的finalize方法
  • 移除GTE CyberTrust Global Root
  • 移除javac的-source, -target對6及1.6的支持,同時移除--release選項

廢棄項

  • 廢棄的API列表見deprecated-list
  • 廢棄-XX:+/-MonitorInUseLists選項
  • 廢棄Default Keytool的-keyalg值

已知問題

  • Swing不支持GTK+ 3.20及之後的版本
  • 在使用JVMCI Compiler(好比Graal)的時候,JVMTI的can_pop_frame及can_force_early_return的capabilities是被禁用的

其餘事項

  • 若是用戶沒有指定user.timezone且從操做系統獲取的爲空,那麼user.timezone屬性的初始值爲空變爲null
  • java.net.URLPermission的行爲發生輕微變化,之前它會忽略url中的query及fragment部分,此次改動新增query及fragment部分,即scheme : // authority [ / path ]變更爲scheme : // authority [ / path ] [ ignored-query-or-fragment ]
  • javax.net.ssl.SSLContext API及Java Security Standard Algorithm Names規範移除了必須實現TLSv1及TLSv1.1的規定

小結

  • java12不是LTS(Long-Term Support)版本(oracle版本纔有LTS),oracle對該版本的support週期爲6個月。這個版本主要有幾個更新點,一個是語法層更新,一個是API層面的更新,另外主要是GC方面的更新。
  • 語法層面引入了preview版本的Switch Expressions;API層面引入了JVM Constants API,引入CompactNumberFormat,讓NumberFormat支持COMPACTSTYLE,對String、Files、Collectors、CompletionStage等新增方法;GC方面引入了experimental版本的Shenandoah GC,不過oracle build的openjdk沒有enable Shenandoah GC support;另外主要對ZGC及G1 GC進行了改進
  • 其中JDK12對ZGC支持了Concurrent Class Unloading,默認是開啓,使用-XX:-ClassUnloading能夠禁用;對於G1 GC則新增支持Abortable Mixed Collections以及Promptly Return Unused Committed Memory特性

doc

相關文章
相關標籤/搜索