1. 程式人生 > >Java: 未來已來

Java: 未來已來

在10月22的 Oracle Codeone大會上,Java 平臺的首席架構師 Mark Reinhold 做了The Future of Java is Today的演講, 回顧了最近 Java 的幾個版本的新的功能,Java 的每年兩次的釋出週期, 澄清了關於釋出流程和 Java 版本的幾個誤區,最後花了很大的篇幅介紹了未來 Java 幾個令人非常期待的幾個孵化中專案,可以為Java帶來更好的生產力、效能和可擴充套件性。我整理了這四個專案相關的知識,你可以提前瞭解到 Java 未來的這些酷炫的特性。

85cbf43ce970c193ff0505e55e6978d0763da106

Mark Reinhold 我不多介紹了, 之前要了解Java的未來動向看Java之父James Gosling, 他離開Oracle之後想了解Java的動向就看 Mark Reinhold。

dbee0426b0e16d9c31c92125acb5cc89fbb48668

Project Amber

提供面向生產力的 Java 特性, 比如字串字面值、switch 表示式、模式匹配、record 等。

這個專案包含很多Java語言特性的新功能。

包括

正在實現的

 ●  JEP 302 Lambda Leftovers:對lambda功能的補強, 比如下劃線變數等 BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i); lambda引數的Shadowing,消除一些歧義等修補工作
 ●  JEP 305 Pattern Matching:這個功能非常好,Scala 和 Kotlin 中的模式匹配非常強大,這個 JEP 提供了類似的功能,配合 switch 和 record,可以大大簡化條件分支的處理,如:

1

2

3

4

5

6

7

8

9

int eval(Node n) {

switch(n) {

case IntNode(int i): return i;

case NegNode(Node n): return -eval(n);

case AddNode(Node left, Node right): return eval(left) + eval(right);

case MulNode(Node left, Node right): return eval(left) * eval(right);

default: throw new

IllegalStateException(n);

};

}

資料類,一行定義,省去了欄位、欄位訪問方法和 hash、equals、toString 等方法,定義 ValueObject 簡化到家了:

1

record Point(int x, int y);

 ●  JEP 325 Switch Expressions (preview, JDK 12): 當前的switch是什麼, 語句。這個jep擴充套件switch,並且可以作為表示式使用:

1

2

3

4

5

6

int numLetters = switch (day) {

case MONDAY, FRIDAY, SUNDAY -> 6;

case TUESDAY -> 7;

case THURSDAY, SATURDAY -> 8;

case WEDNESDAY -> 9;

};

 ●  JEP 326 Raw String Literals (preview, JDK 12): 這個很多語言中都實現了,可以更好的書寫字串字面值, 尤其在正則表示式中處理很多轉義符的時候,和 Go 類似:

1

2

3

4

String s = `

this is my

embedded string

`;

 ●  JEP draft 8209434 Concise Method Bodies: 正常的方法定義以大括號包裹,這個特性提供了類似 Lambda 表示式簡化方式的形式,直接單行定義方法體,類似 C# 和 Kotlin 的特性:

1

2

3

4

5

6

class MyList<T> implements List<T> {

private List<T> aList;

public int size() = aList::size;

public T get(int index) = aList::get;

...

}

已釋出的

●  JEP 286 Local-Variable Type Inference (var) (JDK 10):本地變數的型別推斷, 也就是使用var定義變數,有些同學已經用起來了,非常的方便,有點類似動態型別的語言,感覺雖然還沒有達到Scala那麼靈活,已經很不錯了

 ●  JEP 323 Local-Variable Syntax for Lambda Parameters (JDK 11):對本地變數的型別推斷的加強,用在 Lambda 表示式中。

暫時擱置的

 ●  JEP 301 Enhanced Enums

總之,每一個特性都可以大大簡化我們的開發,讓 Java 更像一個“現代的”程式語言。

Project Loom

提供一個輕量級的使用者態的纖程,叫做 fiber,更加簡化併發程式設計,而且更有效。

這個特性多年前我介紹過: https://colobu.com/2016/08/01/talk-about-quasar-again/,當時它還像一個玩具,開發的時候很麻煩,而且有一些坑。作者後來負責這個 JEP,可以很好的從 Java 實現的角度去實現 fiber,所以很是期待。

ea4d2d9c6a71862a25a639eed0c7553cb60aa454

Mark Reinhold 首先使用 jshell 演示了 fiber 的使用,一兩行程式就可以做到,我覺得方便性可以和 goroutine 相媲美了。他接著使用一個 Restful 的例子比較了 Thread 和 Fiber 的效能, Restful 服務收到請求後暫停100毫秒,模擬一個慢的 IO 操作,結果顯示 Thread 很多幾百毫秒的尖峰,而 fiber 在預熱之後一直穩定在100毫秒。 這絕對是 Java 程式設計師值的關注一個新特性。

885db9ba332cbda645e42f0aa59e1e392c4feecd

例子使用 Jetty 做伺服器,執行緒池執行命令的時候讓 fiber 去排程,這種方式對現有的程式碼改動很小。

59ed588a115702ee08453d12268870100763fd91

我比較關注的是如果它的內部排程演算法怎麼實現的,另外,一個包含複雜業務完成時間較長的 fiber 是否能被排程器自動排程,以便使用有限的執行緒排程其它的 fiber, 類似 goroutine 在系統呼叫的時候自動插入檢查點。

Project Panama

提升 JVM 和外部(非 Java)程式碼和資料聯絡

當然,這個專案不僅僅是簡化JNI的開發,而且提供了很多的特性:

 ●  native function calling from JVM (C, C++), specifically per JEP 191
 ●  native data access from JVM or inside JVM heap
 ●  new data layouts in JVM heap
 ●  native metadata definition for JVM
 ●  header file API extraction tools (see below)
 ●  native library management APIs
 ●  native-oriented interpreter and runtime “hooks”
 ●  class and method resolution “hooks”
 ●  native-oriented JIT optimizations
 ●  tooling or wrapper interposition for safety

 ●  exploratory work with difficult-to-integrate native libraries

6fb4e4f218423d5fc2fcd9f63d4d0030a378cdd5

Mark Reinhold 在演講中舉了兩個例子,首先是為 POSIX 作業系統 API 的標頭檔案 unistd.h 中的函式生成 Java 的可訪問程式碼。

7bb266d8bb1e6e762cca66f0b16b2b98f2bc801e

jextract 工具會生成一堆的函式和型別,關鍵這些是從c的標頭檔案中自動生成的,你不必費勁心思去自己設計型別和方法了。這一點比Go語言中的 CGO 要方便多了,快捷度可以和C#互操作性相媲美。

所以,以後你要是想從 Java 中訪問 C 的連結庫,可以使用 jextract 一步生成,

0ccf569953d623d1d9587e65b6b039c3a199405b

呼叫方法也很方便。

另一個例子是呼叫 C 標準庫 time.h 中的 clock_gettime 函式,它的引數需要 struct 型別,使用上面相同的手段可以生成訪問類:

e7858241743adf39d8fa050cc16542259dfeb9e2

當然這兩個例子只演示了這個專案的一個功能,更多的功能我們可以持續關注。

Project Valhalla

包含兩個Feature:值型別和基本型別的泛型。

 ●  值型別:提供不可變型別和非引用型別的支援。不可變型別在 Scala 中很常用,Java 中也會引進這中型別。使用這種型別有很多好處,一個就是可以顯著地提高效能,因為資料不可變,你也不必擔心同步更新的問題。

 ●  基本型別的泛型: 為 primitive type 提供泛型的支援,不必再進行裝箱開箱操作

1b6961c3b2fa001a2003bf1ebc4eb882daa5b2fe

Mark Reinhold 用一個複數矩陣相乘的例子來測試,測試工具使用 JMH。

首先是正常的 public class Complex {...} 類,然後改成值型別 public value class Complex{...} 再次測試,結果顯示,
正常測試花費3.6秒記憶體分配3.7G;值型別則只需要0.3秒花費3.8M左右,效果驚人!

目前這些特性還在開發之中,Mark Reinhold 用 Java12 + 這些專案已經能跑一些例子了,我們可以期待不遠的將來能在 Java 中使用到這些美妙的特性。


原文釋出時間為:2018-11-22

本文來自雲棲社群合作伙伴“Java雜記”,瞭解相關資訊可以關注“Java雜記”。