Author: Lijbjava
Email: lijb1121@163.com算法
Modularity提供了相似於OSGI框架的功能,模塊之間存在相互的依賴關係,能夠導出一個公共的API,而且隱藏實現的細節,Java提供該功能的主要的動機在於,減小內存的開銷,在JVM啓動的時候,至少會有30~60MB的內存加載,主要緣由是JVM須要加載rt.jar,無論其中的類是否被classloader加載,第一步整個jar都會被JVM加載到內存當中去,模塊化能夠根據模塊的須要加載程序運行須要的class。在引入了模塊系統以後,JDK 被從新組織成 94 個模塊。Java 應用能夠經過新增的 jlink 工具,建立出只包含所依賴的 JDK 模塊的自定義運行時鏡像。這樣能夠極大的減小 Java 運行時環境的大小。使得JDK能夠在更小的設備中使用。採用模塊化系統的應用程序只須要這些應用程序所需的那部分JDK模塊,而非是整個JDK框架了。
JDK9以前提供HttpURLConnection API來實現Http訪問功能,可是這個類基本不多使用,通常都會選擇Apache的Http Client,這次在Java 9的版本中引入了一個新的package:java.net.http,裏面提供了對Http訪問很好的支持,不只支持Http1.1並且還支持HTTP2以及WebSocket,聽說性能特別好。
相似於Python java9引入了jshell這個交互性工具,讓Java也能夠像腳本語言同樣來運行,能夠從控制檯啓動 jshell ,在 jshell 中直接輸入表達式並查看其執行結果。當須要測試一個方法的運行效果,或是快速的對錶達式進行求值時,jshell 都很是實用。 除了表達式以外,還能夠建立 Java 類和方法。jshell 也有基本的代碼完成功能。咱們在教人們如何編寫 Java 的過程當中,再也不須要解釋 「public static void main(String [] args)」 這句廢話。
也叫做只讀集合shell
Java 9增長了List.of()、Set.of()、Map.of()和Map.ofEntries()等工廠方法來建立不可變集合.數據庫
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); //設爲只讀List集合 list = Collections.unmodifiableList(list); System.out.println(list); Set<String> set = new HashSet<>(); set.add("E"); set.add("F"); set.add("G"); //設爲只讀Set集合 set = Collections.unmodifiableSet(set); System.out.println(set); Map<String, String> map = new HashMap<>(); map.put("k1", "v1"); map.put("k2", "v2"); map.put("k3", "v3"); //設爲只讀Map集合 map = Collections.unmodifiableMap(map); System.out.println(map);
List<String> list = List.of("A", "B", "C"); System.out.println(list); Set<String> set = Set.of("E", "F", "G"); System.out.println(set); Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3"); System.out.println(map); /*除了更短和更好閱讀以外,這些方法也能夠避免您選擇特定的集合實現。在建立後,繼續添加元素到這些集合會致使 「UnsupportedOperationException」 。*/
Java 8 爲咱們提供了接口的默認方法和靜態方法,接口也能夠包含行爲,而不只僅是方法定義。數組
默認方法和靜態方法能夠共享接口中的私有方法,所以避免了代碼冗餘,這也使代碼更加清晰。若是私有方法是靜態的,那這個方法就屬於這個接口的。而且沒有靜態的私有方法只能被在接口中的實例調用。安全
interface InterfaceWithPrivateMethods { private static String staticPrivate() { return "static private"; } private String instancePrivate() { return "instance private"; } default void check() { String result = staticPrivate(); InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() { // anonymous class 匿名類 }; result = pvt.instancePrivate(); } }
JDK9在Stream接口中新增4個方法:dropWhile、takeWhile、ofNullable,爲iterate方法新增重載方法。架構
takeWhile能夠用於從 Stream 中獲取一部分數據,接受一個 Predicate 來進行選擇,在有序的 Stream 中,takeWhile 返回從頭開始的儘量多的元素。框架
List<Integer> list = Arrays.asList(45,43,76,87,42,77,90,73,67,88); list.stream().takeWhile((x) -> x < 80 ).forEach(System.out::println); //返回結果 45 43 76
從返回結果能夠看出,takeWhile將會按照list集合有序的從45開始到第一個不符合條件爲止的全部結果。ide
dropWhile 的方法恰好與 takeWhile想法,返回剩餘的元素。模塊化
List<Integer> list = Arrays.asList(45,43,76,87,42,77,90,73,67,88); list.stream().dropWhile((x) -> x < 80 ).forEach(System.out::println); //返回結果 87 42 77 90 73 67 88
從返回結果能夠看出,dropWhile方法恰好和takeWhile方法造成互補,按照list集合有序的返回從第一個不知足條件元素開始到最後爲止的全部結果。
在JDK8 中 Stream 不能徹底爲null,不然會報空指針異常。而在JDK9 中 ofNullable 方法容許建立一個爲空的 Stream。
//NullPointerException //Stream<Object> stream1 = Stream.of(null); //System.out.println(stream1.count()); //不報異常 容許這樣寫 Stream<String> stringStream = Stream.of("AA", "BB", null); System.out.println(stringStream.count()); //不報異常 容許這樣寫 List<String> list = new ArrayList<>(); list.add("A"); list.add(null); System.out.println(list.stream().count()); //ofNullable() :容許值爲 null Stream<Object> stream = Stream.ofNullable(null); System.out.println(stream.count()); Stream<String> stream2 = Stream.ofNullable("Hello World"); System.out.println(stream2.count()); //輸出結果: 3 2 0 1
Optional 類是在JDK8中新增的類,主要是爲了解決空指針異常。在JDK9中對這個類進行了改進,主要是新增了三個方法:stream,ifPresentOrElse 和 or 。
stream方法將Optional轉爲一個 Stream,若是Optional 沒有值就返回一個 Stream.empty。
List<String> list = List.of("A", "B", "C", "D", "E", "F"); Optional<List<String>> optional = Optional.of(list); optional.stream().forEach(System.out::println); Optional<Object> optional1 = Optional.empty(); System.out.println(optional.stream().count()); //輸出結果: [A, B, C, D, E, F] 1
ifPresentOrElse方法:
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
若是 Optional 包含值,則對其包含的值調用函數 action,即 action.accept(value),這與 ifPresent 一致;與 ifPresent 方法的區別在於,ifPresentOrElse 還有第二個參數 emptyAction。若是 Optional 不包含值,那麼 ifPresentOrElse 便會調用 emptyAction,即 emptyAction.run()。
//若是optional包含值,執行action.accept方法。 Optional<Integer> optional = Optional.of(1); optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("沒有值.")); optional = Optional.empty(); //若是optional不包含值,執行emptyAction.run方法。 optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("沒有值.")); //輸出結果: Value: 1 沒有值.
or方法:
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
若是Optional有值,返回 Optional 指定的值,不然返回一個預設的值。
//若是有值返回值。 Optional<String> optional1 = Optional.of("1"); Supplier<Optional<String>> supplierString = () -> Optional.of("沒有值"); optional1 = optional1.or(supplierString); optional1.ifPresent( x -> System.out.println("Value: " + x)); //若是沒值返回預先設定的值。 optional1 = Optional.empty(); optional1 = optional1.or( supplierString); optional1.ifPresent( x -> System.out.println("Value: " + x)); //輸出結果: Value: 1 Value: 沒有值
當一個新版本的 Java 出現的時候,你的庫用戶要花費很長時間纔會切換到這個新的版本。這就意味着庫要去向後兼容你想要支持的最老的 Java 版本 (許多狀況下就是 Java 6 或者 7)。這實際上意味着將來的很長一段時間,你都不能在庫中運用 Java 9 所提供的新特性。幸運的是,多版本兼容 JAR 功能能讓你建立僅在特定版本的 Java 環境中運行庫程序時選擇使用的 class 版本:
JDK9中鑽石操做符可使用匿名實現類,能夠在匿名實現類中重寫方法等操做。
Set<String> set = new HashSet<>(){ //匿名實現類重寫add方法。 @Override public boolean add(String s) { System.out.println("執行add方法"); return super.add(s); } }; set.add("1"); //輸出結果:執行add方法
在JDK8以前可使用「_」單獨的下劃線做爲標識符,但在JDK9中將單獨的下劃線標識符限制使用了,可能後期會將這個標識符作特殊處理如Lambda表達式同樣的->操做符同樣。以下示例:
在JDK8中能夠單獨使用「_」命名
String _ = "Hello"; System.out.println(_); //輸出結果:Hello
在JDK9中回拋出異常
從不少不一樣應用程序收集的信息表名,字符串是堆使用的主要組成部分,並且,大多數字符串對象只包含一個字符,這樣的字符只須要一個字節的存儲空間,所以這些字符串對象的內部char數組中有一半的空間被閒置。 JDK9以前String底層使用char數組存儲數據private final char value[],JDK9將String底層存儲數據改成byte數組存儲數據private final byte[] value。 StringBuffer和StringBuilder也一樣作了變動,將以往char數組改成byte數組。
在 java.awt.image 包下新增了支持多分辨率圖片的API,用於支持多分辨率的圖片。 將不一樣分辨率的圖像封裝到一張(多分辨率的)圖像中,做爲它的變體。 獲取這個圖像的全部變體。 獲取特定分辨率的圖像變體,表示一張已知分辨率單位爲 DPI 的特定尺寸大小的邏輯圖像,而且這張圖像是最佳的變體。 java.awt.image.MultiResolutionImage接口的基礎實現java.awt.image.BaseMultiResolutionImage獲取所須要的變體。 經過接口的getResolutionVariant(double destImageWidth, double destImageHeight)方法,根據分辨率獲取圖像。
智能 java 編譯工具( sjavac )的第一個階段始於 JEP139 這個項目,用於在多核處理器狀況下提高 JDK 的編譯速度。現在,這個項目已經進入第二階段,即 JEP199,其目的是改進 Java 編譯工具,並取代目前 JDK 編譯工具 javac,繼而成爲 Java 環境默認的通用的智能編譯工具。 JDK 9 還更新了 javac 編譯器以便可以將 java 9 代碼編譯運行在低版本 Java 中。
JIT(Just-in-time)編譯器能夠在運行時將熱點編譯成本地代碼,速度很快。可是 Java 項目如今變得很大很複雜,所以 JIT 編譯器須要花費較長時間才能熱身完,並且有些 Java 方法還無法編譯,性能方面也會降低。AoT 編譯就是爲了解決這些問題而生的。 在 JDK 9 中, AOT(JEP 295: Ahead-of-Time Compilation)做爲實驗特性被引入進來,開發者能夠利用新的 jaotc 工具將重點代碼轉換成相似類庫同樣的文件。雖然仍處於試驗階段,但這個功能使得 Java應用在被虛擬機啓動以前可以先將 Java 類編譯爲原生代碼。此功能旨在改進小型和大型應用程序的啓動時間,同時對峯值性能的影響很小。
jdk1.8及以前的JVM詳情參考:http://www.javashuo.com/article/p-ufbnquhs-et.html
Java 9 中 ,JVM 有了統一的日誌記錄系統,可使用新的命令行選項-Xlog 來控制 JVM 上 全部組件的日誌記錄。該日誌記錄系統能夠設置輸出的日誌消息的標籤、級別、修飾符和輸出目標等
jdk1.8及以前的GC機制參考:http://www.javashuo.com/article/p-ufbnquhs-et.html
Java 9 移除了在 Java 8 中 被廢棄的垃圾回收器配置組合,同時把G1設爲默認的垃圾回收器實現。替代了以前默認使用的Parallel GC,對於這個改變,evens的評論是醬紫的:這項變動是很重要的,由於相對於Parallel來講,G1會在應用線程上作更多的事情,而Parallel幾乎沒有在應用線程上作任何事情,它基本上徹底依賴GC線程完成全部的內存管理。這意味着切換到G1將會爲應用線程帶來額外的工做,從而直接影響到應用的性能
java.io.InputStream 中增長了新的方法來讀取和複製 InputStream 中包含的數據。 readAllBytes:讀取 InputStream 中的全部剩餘字節。 readNBytes: 從 InputStream 中讀取指定數量的字節到數組中。 transferTo:讀取 InputStream 中的所有字節並寫入到指定的 OutputStream 中
除以上幾點以外,新特性還有不少。。。
JDK10 可使用var做爲局部變量類型推斷標識符,此符號僅適用於局部變量,加強for循環的索引,以及傳統for循環的本地變量;它不能使用於方法形式參數,構造函數形式參數,方法返回類型,字段,catch形式參數或任何其餘類型的變量聲明。
標識符var不是關鍵字;相反,它是一個保留的類型名稱。這意味着var用做變量,方法名或則包名稱的代碼不會受到影響;但var不能做爲類或則接口的名字(但這樣命名是比較罕見的,由於他違反了一般的命名約定,類和接口首字母應該大寫)。
var str = "ABC"; //根據推斷爲 字符串類型 var l = 10L;//根據10L 推斷long 類型 var flag = true;//根據 true推斷 boolean 類型 var flag1 = 1;//這裏會推斷boolean類型。0表示false 非0表示true var list = new ArrayList<String>(); // 推斷 ArrayList<String> var stream = list.stream(); // 推斷 Stream<String> ============================================================= //反編譯以後的class文件 String str = "ABC"; long l = 10L; boolean flag = true; int flag1 = true; ArrayList<String> list = new ArrayList(); Stream<String> stream = list.stream();
爲了簡化開發,將JDK多存儲庫合併到一個存儲庫中。多年來,JDK的完整代碼已經被分解成多個存儲庫。在JDK9 中有八個倉庫:root、corba、hotspot、jaxp、jaxws、jdk、langtools和nashorn。在JDK10中被合併爲一個存儲庫。 雖然這種多存儲庫模型具備一些優勢,但它也有許多缺點,而且在支持各類可取的源代碼管理操做方面作得不好。特別是,不可能在相互依賴的變動存儲庫之間執行原子提交。例如,若是一個bug修復或RFE的代碼如今同時跨越了jdk和hotspot 存儲庫,那麼對於兩個存儲庫來講,在託管這兩個不一樣的存儲庫中,對兩個存儲庫的更改是不可能實現的。跨多個存儲庫的變動是常見。
這不是讓開發者用來控制垃圾回收的接口;而是一個在 JVM 源代碼中的容許另外的垃圾回收器快速方便的集成的接口。 垃圾回收接口爲HotSpot的GC代碼提供更好的模塊化;在不影響當前代碼的基礎狀況下,將GC添加到HotSpot變的更簡單;更容易從JDK構建中排除GC。實際添加或刪除GC不是目標,這項工做將使HotSpot中GC算法的構建時間隔離取得進展,但它不是徹底構建時間隔離的目標。
JDK10 經過並行Full GC,改善G1的延遲。G1垃圾收集器在JDK 9中是默認的。之前的默認值並行收集器中有一個並行的Full GC。爲了儘可能減小對使用GC用戶的影響,G1的Full GC也應該並行。 G1垃圾收集器的設計目的是避免Full收集,可是當集合不能足夠快地回收內存時,就會出現徹底GC。目前對G1的Full GC的實現使用了單線程標記-清除-壓縮算法。JDK10 使用並行化標記-清除-壓縮算法,並使用Young和Mixed收集器相同的線程數量。線程的數量能夠由-XX:ParallelGCThreads選項來控制,可是這也會影響用Young和Mixed收集器的線程數量。
爲了提升啓動和內存佔用,擴展示有的類數據共享(CDS)特性,容許將應用程序類放置在共享檔案中。 經過在不一樣的Java進程間共享公共類元數據來減小佔用空間。 提高啓動時間。 CDS容許未來自JDK的運行時映像文件($JAVA_HOME/lib/modules)的歸檔類和應用程序類路徑加載到內置平臺和系統類加載器中。 CDS容許將歸檔類加載到自定義類加載器中。
在不執行全局VM安全點的狀況下對線程執行回調的方法。讓它中止單個線程而不是所有線程。
JDK10 從JDK中移除了javah 工具。該工具已被JDK8 (JDK-7150368)中添加javac高級功能所取代。此功能提供了在編譯java源代碼時編寫本機頭文件的功能,從而無需使用單獨的工具。
JDK10 改善 java.util.Locale 類和相關的 API 以實現額外 BCP 47 語言標籤的 Unicode 擴展。尤爲如下擴展支持: cu:貨幣類型 fw:一週的第一天 rg:區域覆蓋 tz:時區 爲支持以上擴展,JDK10對如下API進行更改: java.text.DateFormat::get*Instance:將根據擴展ca、rg或tz返回實例。 java.text.DateFormatSymbols::getInstance:將根據擴展rg返回實例。 java.text.DecimalFormatSymbols::getInstance:將根據擴展rg返回實例。 java.text.NumberFormat::get*Instance:將根據nu或rg返回實例。 java.time.format.DateTimeFormatter::localizedBy:將返回DateTimeFormatter 根據ca,rg或rz的實例。 java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern:將根據rg返回String。 java.time.format.DecimalStyle::of:將返回DecimalStyle根據nu或rg的實例。 java.time.temporal.WeekFields::of:將返回WeekFields根據fw或rg的實例。 java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}:將根據fw或rg返回值。 java.util.Currency::getInstance:將返回Currency根據cu或rg返回實例。 java.util.Locale::getDisplayName:將返回一個包含這些U擴展名的顯示名稱的字符串。 java.util.spi.LocaleNameProvider:將爲這些U擴展的鍵和類型提供新的SPI。
啓用HotSpot VM以在用戶指定的備用內存設備上分配Java對象堆。隨着廉價的NV-DIMM內存的可用性,將來的系統可能配備了異構的內存架構。這種技術的一個例子是英特爾的3D XPoint。這樣的體系結構,除了DRAM以外,還會有一種或多種類型的非DRAM內存,具備不一樣的特徵。具備與DRAM具備相同語義的可選內存設備,包括原子操做的語義,所以能夠在不改變現有應用程序代碼的狀況下使用DRAM代替DRAM。全部其餘的內存結構,如代碼堆、metaspace、線程堆棧等等,都將繼續駐留在DRAM中。 參考如下使用案例: 在多JVM部署中,某些JVM(如守護進程,服務等)的優先級低於其餘JVM。與DRAM相比,NV-DIMM可能具備更高的訪問延遲。低優先級進程能夠爲堆使用NV-DIMM內存,容許高優先級進程使用更多DRAM。 諸如大數據和內存數據庫等應用程序對內存的需求不斷增長。這種應用能夠將NV-DIMM用於堆,由於與DRAM相比,NV-DIMM可能具備更大的容量,成本更低。
啓用基於Java的JIT編譯器Graal,將其用做Linux / x64平臺上的實驗性JIT編譯器。Graal是一個基於Java的JIT編譯器,它是JDK 9中引入的Ahead-of-Time(AOT)編譯器的基礎。使它成爲實驗性JIT編譯器是Project Metropolis的一項舉措,它是下一步是研究JDK的基於Java的JIT的可行性。 使Graal可用做實驗JIT編譯器,從Linux / x64平臺開始。Graal將使用JDK 9中引入的JVM編譯器接口(JVMCI)。Graal已經在JDK中,所以將它做爲實驗JIT將主要用於測試和調試工做。要啓用Graal做爲JIT編譯器,請在java命令行上使用如下選項: -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
在JDK中提供一組默認的root 認證權威(CA)證書。在Oracle的Java SE根CA程序中開源root證書,以使OpenJDK構建對開發人員更有吸引力,並減小這些構建和Oracle JDK構建之間的差別。 cacerts密鑰存儲庫是JDK的一部分,它的目的是包含一組root證書,這些root證書能夠用來在各類安全協議中使用的證書鏈中創建信任。然而,JDK源代碼中的cacerts密鑰庫目前是空的。所以,諸如TLS之類的關鍵安全組件在OpenJDK構建中不會默認工做。爲了解決這個問題,用戶必須配置和填充cacerts密鑰庫,並使用一組root證書來記錄,例如, JDK 9 release notes。
在JEP 223 引入的版本字符串方案比以往有了顯著的改進,可是,該方案並不適合將來,如今Java SE平臺和JDK的新版本嚴格按照六個月的節奏發佈。JEP 223方案的主要困難在於發行版的版本號對於其前身的重要性和兼容性進行了編碼。然而,在基於時間發佈模式中,這些品質並非事先知道的。在發佈的開發週期中,它們可能會發生變化,直到最終的功能被集成爲止。所以發佈的版本號也是未知的。 使用JEP 223的版本號語義,每一個在JDK發佈版上工做或者在其上構建或使用組件的人都必須先說明發布的發佈日期,而後切換到說版本號,已知。維護庫,框架和工具的開發人員必須準備好更改在每一個JDK發佈週期後期檢查版本號的代碼。這對全部參與者來講都很尷尬和混亂。 所以,這裏提出的主要改變是從新編制版本號來編碼,而不是編碼的兼容性和重要性,而是按照發布週期的時間推移。這是更適合基於時間的發佈模型,由於每一個發佈週期,所以每一個發佈的版本號,老是提早知道。 後續的版本格式爲:[1-9][0-9]*((\.0)*\.[1-9][0-9]*)* 該格式能夠是任意長度,但前四個被賦予特定含義,如:$FEATURE.$INTERIM.$UPDATE.$PATCH $FEATURE:功能發佈計數器,無論發佈內容如何,都會爲每一個功能發佈增長。功能可能會添加到功能發佈中; 若是提早通知提早至少發佈一次功能發佈,它們也可能會被刪除。若是合理,可能會作出不兼容的更改。 $INTERIM:臨時版本計數器,對於包含兼容錯誤修復和加強功能的非功能版本遞增,但沒有不兼容的更改,沒有功能移除,也沒有對標準API的更改。 $UPDATE:更新版本計數器增長了兼容更新版本,可解決新功能中的安全問題,迴歸和錯誤。 $PATCH:緊急修補程序釋放計數器只有在須要生成緊急釋放以解決關鍵問題時纔會增長。 版本號永遠不會有零元素結尾。若是一個元素及其後的全部元素在邏輯上具備零值,那麼它們所有被省略。 在嚴格六個月的發佈模式下,版本號以下所示: $FEATURE 每六個月增長一次。如:2018年3月發佈的是JDK 10,2018年9月發佈的是JDK 11,等等。 $INTERIM 老是爲零,由於六個月的模型不包括臨時版本。在此爲保留其靈活性,以便未來對版本模型的修訂可能包括此類版本。 $UPDATE 在$FEATURE發佈後的一個月遞增,以後每三個月遞增一次:如2018年4月發佈JDK 10.0.1。7月發佈的是JDK 10.0.2等等。
正在研究。。。。。。
181:[基於嵌套的訪問控制](http://openjdk.java.net/jeps/181) 309:[動態類 - 文件常量](http://openjdk.java.net/jeps/309) 315:[改進Aarch64內在函數](http://openjdk.java.net/jeps/315) 318:[Epsilon:無操做垃圾收集器](http://openjdk.java.net/jeps/318) 320:[移除Java EE和CORBA模塊](http://openjdk.java.net/jeps/320) 321:[HTTP客戶端(標準)](http://openjdk.java.net/jeps/321) 323:[本地變量Lambda參數](http://openjdk.java.net/jeps/323) 324的[語法](http://openjdk.java.net/jeps/323):[與Curve25519和Curve448的密鑰協議](http://openjdk.java.net/jeps/324) 327:[Unicode 10](http://openjdk.java.net/jeps/327) 328:[飛行記錄器](http://openjdk.java.net/jeps/328) 329:[ChaCha20和Poly1305加密算法](http://openjdk.java.net/jeps/329) 330:[啓動單文件源代碼程序](http://openjdk.java.net/jeps/330) 331:[低開銷堆分析](http://openjdk.java.net/jeps/331) 332:[傳輸層安全性(TLS)1.3](http://openjdk.java.net/jeps/332) 333:[ZGC:可擴展的低延遲垃圾收集器 (實驗性)](http://openjdk.java.net/jeps/333) 335:[棄用Nashorn JavaScript引擎](http://openjdk.java.net/jeps/335) 336:[棄用Pack200工具和API](http://openjdk.java.net/jeps/336)