Java 8 已經出來三年多的時間了,原本計劃2016年七月份release Java 9,但是基於種種原因,Java 9 被推遲到了2017年的3月份,本人也在Open JDK的官網上看到了Java 10的標準也在制定當中,Java的發展真的越來越快了,在Java 9正式發佈之前,我們可以使用它的SNAPSHOT版本,先來體驗一下Java 9 有哪些新的特性,下面的清單來自於官方文檔,看着似乎很多,但是真正具有顛覆意義的其實就是Module System,其餘很多主要是一些新的feature增加,還有一些功能的加強,在本篇文章中,我們將介紹一下主要的幾個,不會一一去說,資料也不多,所以我想說也沒的說,另外Java 8 是我認爲迄今爲止Java 最大的一次變化,不光是特性的增加,更多的是編程風格的轉變,如果你還沒有掌握Java 8,建議你看一下本人錄製的教學視頻,大致40集,專門是針對Java 8特性的實戰視頻,下載地址爲:
https://pan.baidu.com/s/1nvCt83v
102: Process
API Updates
110: HTTP
2 Client
143: Improve
Contended Locking
158: Unified
JVM Logging
165: Compiler
Control
193: Variable
Handles
197: Segmented
Code Cache
199: Smart
Java Compilation, Phase Two
200: The
Modular JDK
201: Modular
Source Code
211: Elide
Deprecation Warnings on Import Statements
212: Resolve
Lint and Doclint Warnings
213: Milling
Project Coin
214: Remove
GC Combinations Deprecated in JDK 8
215: Tiered
Attribution for javac
216: Process
Import Statements Correctly
217: Annotations
Pipeline 2.0
219: Datagram
Transport Layer Security (DTLS)
220: Modular
Run-Time Images
221: Simplified
Doclet API
222: jshell:
The Java Shell (Read-Eval-Print Loop)
223: New
Version-String Scheme
224: HTML5
Javadoc
225: Javadoc
Search
226: UTF-8
Property Files
227: Unicode
7.0
228: Add
More Diagnostic Commands
229: Create
PKCS12 Keystores by Default
231: Remove
Launch-Time JRE Version Selection
232: Improve
Secure Application Performance
233: Generate
Run-Time Compiler Tests Automatically
235: Test
Class-File Attributes Generated by javac
236: Parser
API for Nashorn
237: Linux/AArch64
Port
238: Multi-Release
JAR Files
240: Remove
the JVM TI hprof Agent
241: Remove
the jhat Tool
243: Java-Level
JVM Compiler Interface
244: TLS
Application-Layer Protocol Negotiation Extension
245: Validate
JVM Command-Line Flag Arguments
246: Leverage
CPU Instructions for GHASH and RSA
247: Compile
for Older Platform Versions
248: Make
G1 the Default Garbage Collector
249: OCSP
Stapling for TLS
250: Store
Interned Strings in CDS Archives
251: Multi-Resolution
Images
252: Use
CLDR Locale Data by Default
253: Prepare
JavaFX UI Controls & CSS APIs for Modularization
254: Compact
Strings
255: Merge
Selected Xerces 2.11.0 Updates into JAXP
256: BeanInfo
Annotations
257: Update
JavaFX/Media to Newer Version of GStreamer
258: HarfBuzz
Font-Layout Engine
259: Stack-Walking
API
260: Encapsulate
Most Internal APIs
261: Module
System
262: TIFF
Image I/O
263: HiDPI
Graphics on Windows and Linux
264: Platform
Logging API and Service
265: Marlin
Graphics Renderer
266: More
Concurrency Updates
267: Unicode
8.0
268: XML
Catalogs
269: Convenience
Factory Methods for Collections
270: Reserved
Stack Areas for Critical Sections
271: Unified
GC Logging
272: Platform-Specific
Desktop Features
273: DRBG-Based
SecureRandom Implementations
274: Enhanced
Method Handles
275: Modular
Java Application Packaging
276: Dynamic
Linking of Language-Defined Object Models
277: Enhanced
Deprecation
278: Additional
Tests for Humongous Objects in G1
279: Improve
Test-Failure Troubleshooting
280: Indify
String Concatenation
281: HotSpot
C++ Unit-Test Framework
282: jlink:
The Java Linker
283: Enable
GTK 3 on Linux
284: New
HotSpot Build System
285: Spin-Wait
Hints
287: SHA-3
Hash Algorithms
288: Disable
SHA-1 Certificates
289: Deprecate
the Applet API
290: Filter
Incoming Serialization Data
292: Implement
Selected ECMAScript 6 Features in Nashorn
294: Linux/s390x
Port
295: Ahead-of-Time
Compilation
1. Modular System – Jigsaw Project
該特性是Java 9 最大的一個特性,Java 9起初的代號就叫Jigsaw,最近被更改爲Modularity,Modularity提供了類似於OSGI框架的功能,模塊之間存在相互的依賴關係,可以導出一個公共的API,並且隱藏實現的細節,Java提供該功能的主要的動機在於,減少內存的開銷,我們大家都知道,在JVM啓動的時候,至少會有30~60MB的內存加載,主要原因是JVM需要加載rt.jar,不管其中的類是否被classloader加載,第一步整個jar都會被JVM加載到內存當中去,模塊化可以根據模塊的需要加載程序運行需要的class,那麼JVM是如何知道需要加載那些class的呢?這就是在Java 9 中引入的一個新的文件module.java我們大致來看一下一個例子(module-info.java)
- module com.baeldung.java9.modules.car {
- requires com.baeldung.java9.modules.engines;
- exports com.baeldung.java9.modules.car.handling;
- }
module com.baeldung.java9.modules.car {
requires com.baeldung.java9.modules.engines;
exports com.baeldung.java9.modules.car.handling;
}
關於更多Java 9 模塊編程的內容請參考一本書:《Java 9 Modularity》 裏面講的比較詳細,介紹了當前Java對jar之間以來的管理是多麼的混亂,引入modularity之後的改變會是很明顯的差別。
2. A New Http Client
就目前而言,JDK提供的Http訪問功能,幾乎都需要依賴於HttpURLConnection,但是這個類大家在寫代碼的時候很少使用,我們一般都會選擇Apache的Http Client,此次在Java 9的版本中引入了一個新的package:java.net.http,裏面提供了對Http訪問很好的支持,不僅支持Http1.1而且還支持HTTP2,以及WebSocket,據說性能可以超過Apache HttpClient,Netty,Jetty,簡單的來看一個代碼片段
- URI httpURI = new URI("http://www.94jiankang.com");
- HttpRequest request = HttpRequest.create(httpURI).GET();
- HttpResponse response = request.response();
- String responseBody = response.body(HttpResponse.asString());
URI httpURI = new URI("http://www.94jiankang.com");
HttpRequest request = HttpRequest.create(httpURI).GET();
HttpResponse response = request.response();
String responseBody = response.body(HttpResponse.asString());
3. Process API Enhance
在Java很早的版本中,提供了Process這樣的API可以獲得進程的一些信息,包括runtime,甚至是用它來執行當前主機的一些命令,但是請大家思考一個問題,你如何獲得你當前Java運行程序的PID?很顯然通過Process是無法獲得的,需要藉助於JMX才能得到,但是在這一次的增強中,你將會很輕鬆的得到這樣的信息,我們來看一個簡單的例子
- ProcessHandle self = ProcessHandle.current();
- long PID = self.getPid();
- ProcessHandle.Info procInfo = self.info();
- Optional<String[]> args = procInfo.arguments();
- Optional<String> cmd = procInfo.commandLine();
- Optional<Instant> startTime = procInfo.startInstant();
- Optional<Duration> cpuUsage = procInfo.totalCpuDuration();
ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();
Optional<String[]> args = procInfo.arguments();
Optional<String> cmd = procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();
上面有大量的Optional,這是Java 8中的API,同樣在Java 9中對其進行了增強,本人在Java 8實戰視頻中對Optional API進行了源碼級別的剖析,感興趣的一定要去看看。
已經獲取到了JVM的進程,我們該如何將該進程優雅的停掉呢?下面的代碼給出了答案
- childProc = ProcessHandle.current().children();
- childProc.forEach(procHandle -> {
- assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
- });
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});
通過上面的一小段代碼,我們也發現了Java 9對斷言機制同樣增加了一些增強,多說一些題外話,我們目前的系統中運行一個嚴重依賴於Hive beelineServer的程序,beeline server不是很穩定,經常出現卡頓,甚至假死,假死後也不回覆的問題,這樣就導致我們的程序也會出現卡頓,如果運維人員不對其進行清理,系統運行幾個月之後會發現很多殭屍進程,於是增加一個獲取當前JVM
PID的功能,然後判斷到超過給定的時間對其進行主動殺死,完全是程序內部的行爲,但是獲取PID就必須藉助於JMX的動作,另外殺死它也必須藉助於操作系統的命令,諸如kill這樣的命令,顯得非常的麻煩,但是Java 9的方式明顯要優雅方便許多。
4. Try-With-Resources的改變
我們都知道,Try-With-Resources是從JDK 7 中引入的一項重要特徵,只要接口繼承了Closable就可以使用Try-With-Resources,減少finally語句塊的編寫,在Java 9 中會更加的方便這一特徵
- MyAutoCloseable mac = new MyAutoCloseable();
- try (mac) {
- // do some stuff with mac
- }
- try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
- // do some stuff with finalCloseable
- } catch (Exception ex) { }
MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
// do some stuff with mac
}
try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
// do some stuff with finalCloseable
} catch (Exception ex) { }
我們的Closeable完全不用寫在try()中。
5. Diamond Operator Extension
- FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
- };
- FooClass<? extends Integer> fc0 = new FooClass<>(1) {
- // anonymous inner class
- };
- FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
- };
FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
};
FooClass<? extends Integer> fc0 = new FooClass<>(1) {
// anonymous inner class
};
FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
};
6. Interface Private Method
- 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();
- }
- }}
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();
}
}}
該特性完全是爲了Java 8中default方法和static方法服務的。
7. JShell Command Line Tool
在Java 8 出來的時候,很多人都喊着,這是要搶奪Scala等基於JVM動態語言的市場啊,其中有人給出了一個Java做不到的方向,那就是Scala可以當作腳本語言,Java可以麼?很明顯在此之前Java不行,ta也不具備動態性,但是此次Java 9 卻讓Java也可以像腳本語言一樣來運行了,主要得益於JShell,我們來看一下這個演示
- jdk-9\bin>jshell.exe
- | Welcome to JShell -- Version 9
- | For an introduction type: /help intro
- jshell> "This is my long string. I want a part of it".substring(8,19);
- $5 ==> "my long string"
jdk-9\bin>jshell.exe
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"
這是我們在Jshell這個控制檯下運行,我們如何運行腳本文件呢?
- jshell> /save c:\develop\JShell_hello_world.txt
- jshell> /open c:\develop\JShell_hello_world.txt
- Hello JShell!
jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!
8.JCMD Sub-Commands
記得在Java 8中,放棄了Jhat這個命令,但是很快在Java 9中增加了一些新的命令,比如我們要介紹到的jcmd,藉助它你可以很好的看到類之間的依賴關係
- jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
- 14056:
- java.lang.Object/null
- |--java.net.Socket/null
- | implements java.io.Closeable/null (declared intf)
- | implements java.lang.AutoCloseable/null (inherited intf)
- | |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
- | | implements java.lang.AutoCloseable/null (inherited intf)
- | | implements java.io.Closeable/null (inherited intf)
- | |--javax.net.ssl.SSLSocket/null
- | | implements java.lang.AutoCloseable/null (inherited intf)
- | | implements java.io.Closeable/null (inherited intf)
jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
| implements java.io.Closeable/null (declared intf)
| implements java.lang.AutoCloseable/null (inherited intf)
| |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)
| |--javax.net.ssl.SSLSocket/null
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)
9.Мulti-Resolution Image API
接口java.awt.image.MultiResolutionImage封裝了一系列的不同分辨率圖像到一個單獨對象的API,我麼可以根據給定的DPI 矩陣獲取resolution-specific,看一下下面的代碼片段
- BufferedImage[] resolutionVariants = ....
- MultiResolutionImage bmrImage
- = new BaseMultiResolutionImage(baseIndex, resolutionVariants);
- Image testRVImage = bmrImage.getResolutionVariant(16, 16);
- assertSame("Images should be the same", testRVImage, resolutionVariants[3]);
BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
= new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);
關於AWT的東西,本人幾乎不怎麼接觸,如果有用到的朋友,等JDK 9出來之後,自己體會使用一下吧。
10. Variable Handles
很早之前就傳言Java 會將unsafe這一個類屏蔽掉,不給大家使用,這次看他的官方文檔,貌似所有已sun開頭的包都將不能在application中使用,但是java 9 提供了新的API供大家使用。
在JDK 9中提供了一個新的包,叫做java.lang.invoke裏面有一系列很重要的類比如VarHandler和MethodHandles,提供了類似於原子操作以及Unsafe操作的功能。
11.Publish-Subscribe Framework
在新版的JDK 9 中提供了消息發佈訂閱的框架,該框架主要是由Flow這個類提供的,他同樣會在java.util.concurrent中出現,並且提供了Reactive編程模式。
12. Unified JVM Logging
該特性爲JVM的所有組件引入了一個通用的日誌系統,提供了JVM日誌的基礎設施,你可以不用專門爲了打印某些日誌而添加一些專門的標籤,只需要使用統一的log指令即可,比如:
- java -Xlog:gc=debug:file=gc.txt:none ...
- jcmd 9615 VM.log output=gc_logs what=gc
java -Xlog:gc=debug:file=gc.txt:none ...
jcmd 9615 VM.log output=gc_logs what=gc
13. Immutable Set
其實在Java的早期版本中就已經有這樣的功能了,比如Collections.xxx就可以將某個collection封裝成不可變,但是此次的Java 9版本將其加到了對應的Set和List中,並且有一個專門的新包用來存放這些具體的實現java.util.ImmutableCollections,這一個特性和Scala真的如出一轍。
- Set<String> strKeySet = Set.of("key1", "key2", "key3");
Set<String> strKeySet = Set.of("key1", "key2", "key3");
14. Optional To Stream
對Option提供了stream功能,關於Optional的用法,我在我的教程中講的非常詳細,如果你還沒有掌握,抓緊啊
- List<String> filteredList = listOfOptionals.stream()
- .flatMap(Optional::stream)
- .collect(Collectors.toList());
List<String> filteredList = listOfOptionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
15. 其他
- 大致的特性我就介紹這麼多,你也可以到openJDK官網下載snapshot版本的java 9 來玩一下,當然還有其他很多功能我就不一一介紹了,這裏只是大概的提一下
- 輕量級的json文本處理api
- 移除很多已經被過期的GCC回收器(是移除哦,因爲在Jdk 8 中只是加了過期的標記)
- 使用G1垃圾回收器作爲默認的垃圾回收器
- HTML5風格的java doc
- java doc只是智能搜索功能
- javascript的引擎得到了進一步的升級
- 引入了SHA-3的hash算法
- 大神Doug Lea繼續爲了這個版本的JDK服務,並且還會驚豔到大家。