如約而至,Java 10正式發布!109項新特性一覽
期待已久,沒有跳票的 Java 10 已正式發布!你可以下載 Java 10 正式版:
- http://www.oracle.com/technetwork/java/javase/downloads/index.html
-
http://www.oracle.com/technetwork/java/javase/downloads/jdk10-downloads-4416644.html
此前我們曾報道過,為了更快地迭代,以及跟進社區反饋,Java 的版本發布周期變更為每六個月一次,并且承諾不會跳票。新的發布周期也會嚴格遵循時間點,將在每年的 3 月份和 9 月份發布。所以 Java 10 的版本號是 18.3。
Java 10 是采用新發布周期的第一個版本,提供了 109 項新特性,其中最備受關注的莫過于局部變量的類型推斷。
Java 10 的 12 項關鍵新特性:
- JEP 286: 局部變量的類型推斷。該特性在社區討論了很久并做了調查,可查看 JEP 286 調查結果
- JEP 296: 將 JDK 的多個代碼倉庫合并到一個儲存庫中
- JEP 304: 垃圾收集器接口。通過引入一個干凈的垃圾收集器(GC)接口,改善不同垃圾收集器的源碼隔離性。
- JEP 307: 向 G1 引入并行 Full GC
- JEP 310: 應用類數據共享。為改善啟動和占用空間,在現有的類數據共享(“CDS”)功能上再次拓展,以允許應用類放置在共享存檔中
- JEP 312: 線程局部管控。允許停止單個線程,而不是只能啟用或停止所有線程
- JEP 313: 移除 Native-Header Generation Tool (javah)
- JEP 314: 額外的 Unicode 語言標簽擴展。包括:cu (貨幣類型)、fw (每周第一天為星期幾)、rg (區域覆蓋)、tz (時區) 等
- JEP 316: 在備用內存設備上分配堆內存。允許 HotSpot 虛擬機在備用內存設備上分配 Java 對象堆
- JEP 317: 基于 Java 的 JIT 編譯器(試驗版本)
- JEP 319: 根證書。開源 Java SE Root CA 程序中的根證書
- JEP 322: 基于時間的版本發布模式。“Feature releases” 版本將包含新特性,“Update releases” 版本僅修復 Bug
Java 10 的 109 項新特性一出,社區就有熱心用戶翻譯成了中文版,在此感謝他們的努力,下面我們來看看這 109 項新特性都有哪些?
JDK 10 的 109 項新特性
突然感覺 JDK9 發布才僅僅幾周的時間,然而,隨著新的 OpenJDK 的發布節奏,JDK10 已經到達發布候選里程碑階段。
我看過各種關于 JDK10 新特性的博客,但是它們都傾向于關注通過 JEPS 定義的大方面。這篇博文,我將看看是否可以羅列出 JDK10 中已經發生變化的方方面面(包括新增的和剔除的)。
有時候,我會做一些關于 Java SE 的報告會。之前我在“ JDK9 的 55 個新特性”的報告會上曾開玩笑說:下次我將做的恐怕是“ JDK10 的 5 個新特性”。然而事實證明,即使僅有六個多月的開發時間,JDK10 依然超乎想象。
即便我不再為 Oracle 工作,我也在此先做一個“安全港聲明”,以便消除誤會。這個列表是由下面這些公開可用的信息整理編輯的:JDK Enhancement Proposals (JEPs)、the OpenJDK bug database 和 Java SE 10 public review specification (JSR 383) 。當然,盡管我已盡可能的研究以保證信息準確,但在 JDK 10 最終發布之前仍可能會發生變化。
大事記
JDK10 包含 12 個JEP (改善提議):
- 【286】局部變量類型推斷 :對于開發者來說,這是 JDK10 唯一的真正特性。它向 Java 中引入在其他語言中很常見的 var ,比如 JavaScript 。只要編譯器可以推斷此種類型,你不再需要專門聲明一個局部變量的類型。一個簡單的例子是:
var x = new ArrayList<String>();
這就消除了我們之前必須執行的 ArrayList<String> 類型定義的重復。我鼓勵你們去讀 JEP ,因為上面有一些關于這個句法是否能用的規則。
有趣的是,需要注意 var 不能成為一個關鍵字,而是一個保留字。這意味著你仍然可以使用 var 作為一個變量,方法或包名,但是現在(盡管我確定你絕不會)你不能再有一個類被調用。
- [310]應用類數據共享(CDS) :CDS 在 JDK5 時被引進以改善 JVM 啟動的表現,同時減少當多個虛擬機在同一個物理或虛擬的機器上運行時的資源占用。
JDK10 將擴展 CDS 到允許內部系統的類加載器、內部平臺的類加載器和自定義類加載器來加載獲得的類。之前,CDS 的使用僅僅限制在了 bootstrap 的類加載器。
- [314]額外的 Unicode 語言標簽擴展:這將改善 java.util.Locale 類和相關的 API 以實現額外 BCP 47 語言標簽的 Unicode 擴展。尤其是,貨幣類型,一周的第一天,區域覆蓋和時區等標簽現在將被支持。
- [322]基于時間的版本控制:正如我在之前的博客中所討論的,我們的 JDK 版本字符串格式幾乎與 JDK 版本一樣多。有幸的是,這是最后需要使用到的,我們可以堅持用它。這種格式使用起來很像 JDK9 中介紹的提供一個更加語義的形式。有一件困擾我的事是包含了一個 INTERIM 元素,正如 JEP 提議中所說,“永遠是0”。好吧,如果永遠是0,那它有什么意義呢?他們說這是為未來使用做保留,但我仍不是很贊同。我認為,這有些冗余繁雜。
這也消除了在 JDK9 中有過的相當奇怪的情形。第一次更新是 JDK 9.0.1 , 非常符合邏輯。第二次更新是 JDK 9.0.4 ,不合邏輯。原因是,在 JDK9 的版本計數模式下,需要留下空白以便應急或不在預期安排的更新使用。但既然沒有更新是必須的,為什么不簡單稱之為 JDK 9.0.2 呢?
- [319]根證書:在 JDK 中將提供一套默認的 CA 根證書。關鍵的安全部件,如 TLS ,在 OpenJDK 構建中將默認有效。這是 Oracle 正在努力確保 OpenJDK 二進制和 Oracle JDK 二進制功能上一樣的工作的一部分,是一項有用的補充內容。
- [307] 并行全垃圾回收器 G1 : G1 是設計來作為一種低延時的垃圾回收器(但是如果它跟不上舊的堆碎片產生的提升速率的話,將仍然采用完整壓縮集合)。在 JDK9 之前,默認的收集器是并行,吞吐,收集器。為了減少在使用默認的收集器的應用性能配置文件的差異,G1 現在有一個并行完整收集機制。
- [313]移除 Native-Header 自動生成工具:Java9 開始了一些對 JDK 的家務管理,這項特性是對它的延續。當編譯 JNI 代碼時,已不再需要單獨的工具來生成頭文件,因為這可以通過 javac 完成。在未來的某一時刻,JNI 將會被 Panama 項目的結果取代,但是何時發生還不清楚。
- [304]垃圾回收器接口: 這不是讓開發者用來控制垃圾回收的接口;而是一個在 JVM 源代碼中的允許另外的垃圾回收器快速方便的集成的接口。
- [312]線程-局部變量管控:這是在 JVM 內部相當低級別的更改,現在將允許在不運行全局虛擬機安全點的情況下實現線程回調。這將使得停止單個線程變得可能和便宜,而不是只能啟用或停止所有線程。
- [316]在備用存儲裝置上的堆分配:硬件技術在持續進化,現在可以使用與傳統 DRAM 具有相同接口和類似性能特點的非易失性 RAM 。這項 JEP 將使得 JVM 能夠使用適用于不同類型的存儲機制的堆。
- [317] 試驗性的基于 Java 的 JIT 編譯器:最近宣布的 Metropolis 項目,提議用 Java 重寫大部分 JVM 。乍一想,覺得很奇怪。如果 JVM 是用 Java 編寫的,那么是否需要一個 JVM 來運行 JVM ? 相應的,這導致了一個很好的鏡像類比。 現實情況是,使用 Java 編寫 JVM 并不意味著必須將其編譯為字節碼,你可以使用 AOT 編譯,然后在運行時編譯代碼以提高性能。
這項 JEP 將 Graal 編譯器研究項目引入到 JDK 中。并給將 Metropolis 項目成為現實,使 JVM 性能與當前 C++ 所寫版本匹敵(或有幸超越)提供基礎。
-
[296]: 合并 JDK 多個代碼倉庫到一個單獨的儲存庫中:在 JDK9 中,有 8 個倉庫: root、corba、hotspot、jaxp、jaxws、jdk、langtools 和 nashorn 。在 JDK10 中這些將被合并為一個,使得跨相互依賴的變更集的存儲庫運行 atomic commit (原子提交)成為可能。
新 API
有 73 項新增內容添加到了標準類庫中。
- java.awt.Toolkit
int getMenuShortcutKeyMaskEx() : 確定哪個擴展修飾符鍵是菜單快捷鍵的適當加速鍵。
- java.awt.geom.Path2D :
void trimToSize() : 將此 Path2D 實例的容量計算到它當前的大小。應用可使用此操作將路徑的存儲空間最小化。這個方法也被添加到 Path2D.Double 和 Path2D.Float 類。
- java.io.ByteArrayOutputStream:
String toString(Charset) : 重載 toString(),通過使用指定的字符集解碼字節,將緩沖區的內容轉換為字符串。
- java.io.PrintStream:
lang.io.PrintWriter:
這兩個類都有三個新的構造函數,它們需要額外的 Charset 參數。
- java.io.Reader:
long transferTo(Writer): 從這個 Reader 中讀取所有字符,并按照所讀的順序將字符寫入給定的 Writer 。
- java.lang.Runtime.Version:
有四種新方法返回新(JEP 322)版本字符串字段的整數值: feature()、interim()、patch() 和 update() 。
- java.lang.StackWalker.StackFrame :
String getDescriptor() : 按照 JVM 標準返回此堆棧幀所代表的方法的描述符。
String getMethodType() :返回此堆棧幀所代表的方法類型,描述參數類型和返回值類型。
- java.lang.invoke.MethodType:
Class<?> lastParameterType(): 返回這個方法類型的最后一個參數類型。如果這個方法類型沒有參數,則返回空類型作為崗哨值( Sentinel Value )。
- java.lang.management.RuntimeMXBean:
long getPid(): R 返回正在運行的 JVM 的進程 ID 。
- java.lang.management.ThreadMXBean:
ThreadInfo[] dumpAllThreads(boolean, boolean, int): 返回所有活動線程的線程信息,其中有指定的最大元素數量和同步信息的堆棧跟蹤。
ThreadInfo[] getThreadInfo(long[], boolean, boolean, int): 返回每個線程的線程信息,這些線程的標識位于輸入數組中,其中有指定的最大元素數量和同步信息的堆棧跟蹤。
- java.lang.reflect.MalformedParameterizedTypeException: 添加了一個新的構造函數,它以字符串的形式作為參數來獲取詳細信息。
-
java.net.URLDecoder:
java.net.URLEncoder:
這兩個類都有新的重載的解碼和編碼方法,將 charset 作為附加參數。 - java.nio.channels.Channels:
兩個新的靜態重載方法,允許使用 Charset 的 newReader(ReadByteChannel,Charset)和newWriter(WriteByteChannel,Charset)。
- java.nio.file.FileStore:
long getBlockSize(): 在這個文件存儲中返回每個塊的字節數。
- java.time.chrono: 這個包里有三個類,HijrahEra、MiinguoEra 和 ThaiBuddhistEra ,都有同樣的方法。
String getDisplayName(TextStyle, Locale): 這將返回用于識別 era 的文本名稱,適合于向用戶展示。
- java.time.format.DateTimeFormatter:
localizedBy(Locale): 返回指定格式器的一個副本,其中包含地區、日歷、區域、小數和/或時區的本地化值,這將取代該格式器中的值。
- java.util : DoubleSummaryStatistics、IntSummaryStatistics 和 LongSummaryStatistics 都有一個新的構造函數,它包含 4 個數值。它使用指定的計數、最小值、最大值和總和構造一個非空實例。
-
java.util.List:
java.util.Map:
java.util.Set: 這些接口中的每一個都增加了一個新的靜態方法,copyOf(Collection)。這些函數按照其迭代順序返回一個不可修改的列表、映射或包含給定集合的元素的集合。 -
java.util.Optional:
java.util.OptionalDouble:
java.util.OptionalInt:
java.util.OptionalLong: 每一個類都有一個新的方法,orElseThrow() ,它本質上和 get() 一樣,也就是說,如果 Optional 有值則返回。否則,將拋出 NoSuchElementException 。 -
java . util.Formatter:
java.util.Scanner:
這兩個類都有三個新的構造函數,除了其他參數之外,它們都帶有一個 charset 參數。 - java.util.Properties : 這有一個新的構造函數,它接受一個 int 參數。這將創建一個沒有默認值的空屬性列表,并且指定初始大小以容納指定的元素數量,而無需動態調整大小。還有一個新的重載的 replace 方法,接受三個 Object 參數并返回一個布爾值。只有在當前映射到指定值時,才會替換指定鍵的條目。
-
java . SplittableRandom :
void nextBytes(byte[]): 用生成的偽隨機字節填充一個用戶提供的字節數組。 -
java.util.concurrent.FutureTask : 添加了 toString() 方法,該方法返回一個標識 FutureTask 的字符串,以及它的完成狀態。在括號中,狀態包含如下字符串中的一個,“Completed Normally” 、“Completed Exceptionally”、 “Cancelled” 或者 “Not completed”。
-
java.util.concurrent.locks.StampedLock :
boolean isLockStamp(long) : 返回一個標記戳表示是否持有一個鎖。
boolean isOptimisticReadStamp(long) : 返回一個標記戳代表是否成功的進行了樂觀讀(optimistic read)。
boolean isReadLockStamp(long): 返回一個標記戳表示是否持有一個非獨占鎖(即 read lock )。
boolean isWriteLockStamp(long) : 返回一個標記戳表示是否持有一個獨占鎖(即 write lock )。 -
java . jar.JarEntry:
String getRealName() : 返回這個 JarEntry 的真實名稱。如果這個 JarEntry 是一個多版本 jar 文件的入口,它被配置為這樣處理,這個方法返回的名字是 JarEntry 所代表的版本條目的入口,而不是 ZipEntry.getName() 返回的基本條目的路徑名。如果 JarEntry 不代表一個多版本 jar 文件的版本化條目或者 jar 文件沒有被配置為作為一個多版本 jar 文件進行處理,這個方法將返回與 ZipEntry.getName() 返回的相同名稱。 -
java.util.jar.JarFile:
Stream<JarEntry> versionedStream() : 返回 jar 文件中指定版本的入口對應 Stream 。與 JarEntry 的 getRealName 方法類似,這與多版本 jar 文件有關。 -
java.util.spi.LocaleNameProvider:
getDisplayUnicodeExtensionKey(String, Locale): 為給定的 Unicode 擴展鍵返回一個本地化名稱。
getDisplayUnicodeExtensionType(String, String, Locale): 為給定的 Unicode 擴展鍵返回一個本地化名稱。 -
java.util.stream.Collectors:
toUnmodifiableList():
toUnmodifiableSet():
toUnmodifiableMap(Function, Function):
toUnmodifiableMap(Function, Function, BinaryOperator): 這四個新方法都返回 Collectors ,將輸入元素聚集到適當的不可修改的集合中。 - java.lang.model.SourceVersion : 現在有了一個字段,它代表了 JDK 10 的版本。
-
java.lang.model.util.TypeKindVisitor6 :
javax.lang.model.util.TypeKindVisitor9:
(我必須承認,我從來沒聽說過這些類)
R visitNoTypeAsModule(NoType, P) : 訪問一個 MODULE 的 pseudo-type 。我不確定為什么只有這兩個類得到這個方法,因為還有 Visitor7 和 Visitor8 變量。 -
javax.remote.management.rmi.RMIConnectorServer :
這個類已經添加了兩個字段: CREDENTIALS_FILTER_PATTERN 和 SERIAL_FILTER_PATTERN 。 -
javax . ButtonModel :看,Swing 還在更新!
ButtonGroup getGroup(): 返回按鈕所屬的組。通常用于單選按鈕,它們在組中是互斥的。 -
javax . plaf.basic.BasicMenuUI :
Dimension getMinimumSize(JComponent): 返回指定組件適合觀感的最小大小。
JVM 規范改動
這些改動相當小:
- 4.6節:類文件格式(第99頁)。在方法訪問標志方面有小的改動。
- 4.7節:模塊屬性(第169頁)。如果模塊不是 java.base ,則 JDK 10 不再允許設置 ACC_TRANSITIVE 或 ACC_STATIC_PHASE 。
- 4.10節:類文件的校驗(第252頁)。dup2 指令已改變了 typesafe form 1 的定義,顛倒了 canSafleyPushList 一節中類型的順序(你需要仔細查看才能發現它)。
- 5.2節:Java 虛擬機啟動(第350頁)。該描述添加了在創建初始類或接口時可使用用戶定義的類加載器( bootstrap 類加載器除外)。
對 Java 語言規范的更改
這里還有一些更改,但主要是為了支持局部變量類型推斷。
- 第3.8節:標識符(第23頁)。在忽略了可忽略的字符之后,標識符的等價性現在被考慮了。這似乎是合乎邏輯的。
- (第24頁)一個新的 Token,TypeIdentifier,它支持對局部變量類型推斷的新用法,而 var 的使用不是關鍵字,而是一個具有特殊含義的標識符,作為局部變量聲明的類型。
- 第4.10.5節:類型預測(第76頁)。這是一個相當復雜的部分,它涉及到捕獲變量、嵌套類以及如何使用局部變量類型推斷。我建議你閱讀規范中的這一部分,而不是試圖解釋它。
- 第6.1節:聲明(第134頁)。一個反映使用 TypeIdentifier 來支持局部變量類型的推斷的小改動。
- 第6.5節:確定名字的含義(第153頁,第158頁和第159頁)。根據類型標識符的使用而更改類類型。
- 第6.5.4.1:簡單的 PackageOrTypeNames(第160頁)
- 第6.5.4.2節:合規的 PackageOrTypeNames(第160頁)。這兩種方式都與使用 TypeIdentifier 有細微的變化。
- 第7.5.3:單靜態導入聲明(第191頁)。這改變了導入具有相同名稱的靜態類型的規則。除非類型是相同的,否則這將成為一個錯誤,在這種情況下,重復被忽略。
- 第7.7.1:依賴(第198頁)。如果你明確聲明一個模塊需要 java.base ,那在必要的關鍵字之后,你就不能再使用修飾符(例如靜態)了。
- 第8部分:正式參數(第244頁)。接收者參數可能只出現在一個實例方法的 formalparameters 列表,或者是一個內部類的構造函數中,其中內部類沒有在靜態上下文中聲明。
- 第9.7.4節:注釋可能出現的地方(第335頁)。有一個與局部變量類型推斷相關的變更。
- 第14.4部分:局部變量聲明語句(第433頁)。實現局部變量類型推斷所需的大量更改。
- 第14節:增強的 for 語句(第455頁)。這個結構已經更新,包括對局部變量類型推斷的支持。
- 第14.20.3節:try-with-resources(474頁)。這個結構已經更新,包括對局部變量類型推斷的支持。
最后,第 19 章有多處語法更新,反映了應更多使用 TypeIdentifier 類型標識符,而不僅僅是 Identifier 標識符,以支持局部變量類型推斷。
雜項
- 如果 Kerberos 的配置文件 krb5.conf 包含一個 INCLUDEDIR 選項,那么在 INCLUDEDIR 這個目錄下所有以 .conf 結尾的文件都會被默認加載進來。
-
以前版本中已經過期的 Java 的啟動選項 -d32 和 –d64 在當前版本已經被移除。如果你在新的版本里仍然使用了這兩個選項,JVM 將無法正常啟動。
-
JDK10 支持 JDK9 中的新版本 Doclet,JDK6、JDK7、JDK8 中的 Doclet 版本都不再支持。
-
JDK10 重新啟用了在 JDK9 中被不當過時的 newFactory() 方法。
-
JDK10 引入了一個新的 Javadoc 標簽: {@summary…},解決了以前版本無法生成 API 摘要的問題。
-
JDK10 去掉了 BiasedLockingStartupDelay 的 4 秒啟動延時。
-
以下在 com.sun.security.auth 包中的過時的類在新版本中都已經被移除:
-
PolicyFile
-
SolarisNumericGroupPrincipal
-
SolarisNumericUserPrincipal
-
X500Principal
-
SolarisLoginModule
-
SolarisSystem
-
-
在 java.lang.SecurityManager 類中的以下屬性和方法(從 JDK 1.2 就已經過時)終于被移除了:
-
inCheck (屬性)
-
getInCheck
-
classDepth
-
classLoaderDepth
-
currentClassLoader
-
currentLoadedClass
-
inClass
-
inClassLoader
-
-
以下 java.lang.Runtime 類中已經被廢棄的國際化方法在新版本被移除:
-
getLocalizedInputStream
-
getLocalizedOutputStream
-
-
以下廢棄的 Hotspot –X 選項在新版本中被移除:-Xoss, -Xsqnopause, -Xoptimize, -Xboundthreads and –Xusealtsigs.
-
policytool 在新版本中被移除。
-
javadoc 工具在新版本中可以通過 –add-stylesheets 命令選項支持多個 stylesheets 。
-
新版本的 JVM 能夠根據系統分配給當前 Docker 容器的 CPU 數和內存來配置線程池和 GC 機制,而不再是直接使用系統的 CPU 和內存。并且增加了三個更強大的命令選項:-XX:InitialRAMPercentage、-XX:MaxRAMPercentage 和 -XX:MinRAMPercentage 。
-
新版本增加了一個新的系統屬性:jdk.disableLastUsageTracking。這個新增的屬性就像它的名字一樣,會禁用 JRE 的上一次使用跟蹤。
如上所述,盡管距離 JDK 9 發布僅有六個月的時間,但 JDK 10 實際上有相當多的變化。當然,它們中的一些是非常小的變更,但我認為這表明目前每 6 個月發布一次的節奏,將在 Java 平臺快速迭代改進方面起到作用。
同時也讓我們期待 JDK 11 將帶來些什么…
相關鏈接
JDK 10 安裝指南:
- http://docs.oracle.com/javase/10/docs/technotes/guides/install/install_overview.html
JDK 10 發布說明:
- http://www.oracle.com/technetwork/java/javase/documentation/10u-relnotes-4108739.html
新特性:
- http://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html#NewFeature
ReadMe:
- http://www.oracle.com/technetwork/java/javase/documentation/jdk10-readme-4419830.html
來自: http://developer.51cto.com/art/201803/568613.htm