2020/04/18

Java 9 以降の新機能ピックアップ

最近、現役で現場で Java エンジニアやっている人の話をいくつか聞いていると、Java の機能についての理解が Java 8 までで止まっている人が多い気がしました。Oracle 版の有償化やサポートライフサイクルの変更などの影響で、Java 8 の延長サポートを使っているシステムが多く、Java 9 以降の経験を積んでいる Java エンジニアがあまり増えていないのではないかな、と思っています。

ここでは、Java 9 以降 Java 13 までに追加された機能をいくつか抜粋して紹介したいと思います。
Java 14 についてはこちらの記事をご覧ください。

Java 9

JEP 102: Process API Updates

Process API が拡張され、java.lang.Process から取得できる情報が増えたり、新クラス java.lang.ProcessHandle を使用してより詳細に外部プロセスを監視・制御できるようになりました。

JEP 200: The Modular JDK

JEP 201: Modular Source Code

JEP 220: Modular Run-Time Images

JEP 260: Encapsulate Most Internal APIs

JEP 261: Module System

JEP 282: jlink: The Java Linker

いわゆる Project Jigsaw です。語り始めると長くなりそうなので、また別の機会に……。

JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)

Java のインタラクティブシェルが追加されました。

JEP 259: Stack-Walking API

スタックフレームの情報にきれいにアクセスできる API が追加されました。

JEP 269: Convenience Factory Methods for Collections

各種 Collection のファクトリメソッドが追加されています。List::of, Set::of, Map::of など。

JEP 280: Indify String Concatenation

Indify とは、Invoke Dynamic 化という意味です。
String の結合 (+ 演算子) は、これまで StringBuilder を使うようにコンパイルされていましたが、Java 9 からはまったく違う方法になりました。
結合後の合計のバイト長ちょうどのバイト配列を先に用意して、各 String の内部バッファを適切な位置にコピーします。こうすることで、初回の Invoke Dynamic のブートストラップ処理を除けば高速化します。

Java 10

JEP 286: Local-Variable Type Inference

初期化付きで変数を宣言するときに、変数の型を明示せず、var という仮想型名を書くと、初期化子の型から推論して変数の型を決めてくれる、という記法が導入されました。
変数の型はコンパイル時に決まります。何でも入れていい変数になるわけではありません。

Java 11

JEP 318: Epsilon: A No-Op Garbage Collector (Experimental)

Epsilon GC は、ガーベジをコレクションしないガーベジコレクタです。メモリの割り当てはしますが、解放はしません。ヒープが無くなったら終了です。
一見意味が無いように思えますが、以下のような用途があります。
  • パフォーマンス計測、メモリ使用量確認といった、GC の影響の無い状態で挙動を観測したい場合
  • VM を開発するとき
  • ヒープが足りることが分かっている短いプログラムを動かすとき
  • 限界までレイテンシやスループットを改善したいとき

JEP 321: HTTP Client (Standard)

HTTP クライアントが標準 API に入りました。HTTP/2 にも対応しています。

JEP 323: Local-Variable Syntax for Lambda Parameters

Lambda 式のパラメータに var キーワードを付けることができるようになりました。
元々型推論されるので、直接的な意味は無いのですが、こうすることで @NotNull などのアノテーションを付与できるようになりました。

JEP 328: Flight Recorder

JDK Flight Recorder が導入されました。

JEP 330: Launch Single-File Source-Code Programs

単一のソースファイルで出来ているプログラムについて、ソースファイルを直接 java コマンドに渡すと、実行してくれるようになりました。
これまでは javac Main.java; java Main といった要領でしたが、なんと java Main.java でいきなり実行してくれます。class ファイルも生成されません。
さらに、--source <version> 引数でソースバージョンを指定できるのですが、--source が指定されているときは、拡張子が java でなくても構わなくなります。
これが何を意味するかというと、UNIX 系 OS でスクリプトのように使えるということになります。
#!/usr/bin/env java --source 14
public class SingleFile {
  public static void main(final String[] args) {
    System.out.println("Hello, World!");
  }
}

こういう内容で SingleFile というファイルを作っておき、chmod +x して path を通しておけば、SingleFile というコマンドとして使うことができます。

気軽に Java プログラムを書いてビルド無しで実行できるというのは、案外便利かもしれません。

Java 12〜13

ここらはあまりめぼしいものはありません。