Java 10は、その23年の歴史の中で最も速いJavaバージョンのリリースです。Javaは成長と進化の遅さについて批判されてきましたが、Java 10はその概念を打ち砕きました。Java 10は多くの未来志向の変更が加えられたリリースであり、そのスコープと影響は明白ではないかもしれませんが、遠大です。この記事では、Java 10リリースに追加されたさまざまな機能について議論します。その前に、Javaリリースモデルに導入されたいくつかの変更を確認しましょう。
長期サポートモデル
2017年以降、OracleとJavaコミュニティはJavaの新しい6ヶ月のリリースサイクルに移行することを発表しました。Oracle Java SE製品には長期サポート(LTS)モデルが導入されました。これは何を意味するのでしょうか?製品のLTSバージョンは、Oracleからの優れたサポートを提供し、対象は3年ごとです。各Javaリリースは1つまたは2つの主要な機能に基づいてモデル化され、これらの機能がリリースを推進します。障害が発生するとリリースが延期され、市場投入が遅れます。Java 9の主要な機能であるProject Jigsawは、リリース日を数回押し戻し、リリースは1.5年以上遅れました。6ヶ月ごとのリリースサイクルはリリーストレインに従います。リリーストレインは6ヶ月ごとにスケジュールされます。対象となる機能がリリーストレインに乗る。それ以外の場合は、次のスケジュールされたトレインを待ちます。
Oracle JDK vs Open JDK
開発者にとってより使いやすいように、OracleとJavaコミュニティは今後、OpenJDKバイナリを主要なJDKとして推進しています。これは以前の日々からの大きな救済であり、以前はJDKバイナリがOracleによって所有され、ライセンスされており、再配布に関するさまざまな制限がありました。Oracleは、長期サポートリリースのためにのみ、彼らのJDKを生産し続ける予定です。これは、クラウドおよびコンテナフレンドリーになる方向への動きであり、オープンJDKバイナリはコンテナの一部として配布できます。 これは何を意味するのでしょうか? OpenJDKバイナリは6ヶ月ごとにリリースされますが、Oracle JDKバイナリは3年ごとにリリースされます(LTSバージョン)。 どのJDKバイナリが採用されますか? 大規模な組織はバージョン間の移行に時間がかかります。彼らはできる限りバージョンに固執します。 Java 6の業界採用はJava 7よりも多かったですが、業界は徐々にJava 8に移行しています。個人的には、LTSバージョンが企業にとって最も好ましいものになると考えています。ただし、Oracle JDKのLTSバージョンかOpenJDKのLTSバージョンかはまだわかりません。それは一部、クラウド空間で多くのことが進行中であるためです。 Java 9と10は非LTSリリースです。2018年9月にリリース予定のJava 11はLTSリリースになります。
Java 10の機能
Java 10で利用可能な機能をちょっと覗いてみましょう。
タイムベースのリリースサイクルの採用に伴い、OracleはJava SEプラットフォームとJDKのバージョン文字列スキーム、および現在と将来の時間ベースのリリースモデルの関連するバージョン情報を変更しました。バージョン番号の新しいパターンは次のとおりです:$FEATURE.$INTERIM.$UPDATE.$PATCH
$FEATURE:カウンタは6か月ごとにインクリメントされ、機能リリースバージョンに基づきます。例:JDK 10、JDK 11。 $INTERIM:カウンタは、互換性のあるバグ修正と機能強化を含む非機能リリースのためにインクリメントされますが、互換性のない変更はありません。通常、これはゼロになります。6か月の間に中間リリースがないためです。これは将来のリリースモデルの改訂のために保持されます。 $UPDATE:カウンタは、セキュリティの問題、リグレッション、および新しい機能のバグを修正する互換性のある更新リリースのためにインクリメントされます。これは機能リリースの1か月後に更新され、その後3か月ごとに更新されます。2018年4月のリリースはJDK 10.0.1であり、7月のリリースはJDK 10.0.2などです。$PATCH:カウンタは、致命的な問題を修正するための緊急リリースのためにインクリメントされます。これらのカウンタ値をプログラムで取得するための新しいAPIが追加されました。これを見てみましょう。
Version version = Runtime.version();
version.feature();
version.interim();
version.update();
version.patch();
さて、バージョン情報を返すJavaランチャーを見てみましょう。
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
バージョン番号の形式は、「10」となっています。他のカウンタがゼロ以外であるためです。リリース日が追加されています。18.3は2018年の3月、ビルド10+46はバージョン10の46番目のビルドを意味します。仮想的なJDK 10.0.1のビルド93の場合、ビルドは10.0.1+939になります。### ローカル変数の型推論(JEP 286)
開発者にとって、Java 10で最も大きな新機能は、ローカル変数の型推論です。これにより、初期化子を持つローカル変数の宣言に型推論を追加することができます。ローカル型推論は、以下のシナリオでのみ使用できます:
- 初期化子を持つローカル変数に限定されます
- 強化されたforループのインデックス
- forループ内で宣言されたローカル変数
使用方法を見てみましょう:
var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList
// 強化されたforループのインデックス
for (var number : numbers) {
System.out.println(number);
}
// ループ内で宣言されたローカル変数
for (var i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
詳細については、java 10 ローカル変数の型推論の専門記事で読むことができます。13. ### 実験的なJavaベースのJITコンパイラ(JEP 317)
この機能により、JavaベースのJITコンパイラであるGraalをLinux/x64プラットフォームで実験的なJITコンパイラとして使用できます。これはJava 10の機能リストにおいて最も未来志向のものです。GraalはJava 9で導入されました。これはこれまで使用してきたJITコンパイラの代替です。これはJVMへのプラグインであり、JITコンパイラがJVMに固定されておらず、動的にプラグインと交換することができます。また、Javaの世界にAhead of Time(AOT)コンパイレーションをもたらします。さらに、多言語の解釈をサポートしています。「Javaバイトコードをマシンコードに変換するためのJavaベースのジャストインタイムコンパイラ。」これは混乱していますか?もしJVMがJavaで書かれているなら、JVMを実行するためにはJVMが必要ではありませんか? JVMはAOTでコンパイルされ、その後JITコンパイラがライブコード最適化を介してパフォーマンスを向上させるためにJVM内で使用できます。 GraalはJavaで完全にゼロからJITコンパイラを書き直したものです。以前のJITコンパイラはc++で書かれていました。これは任意のプログラミング言語の最終段階の進化の1つと考えられています。Graalに切り替えるには、次のJVMパラメータを使用できます:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Graalについて詳しくは、Chris Seatonのプレゼンテーションから学ぶことができます。16. ### アプリケーションクラスデータ共有(JEP 310)
この機能は、スタートアップのフットプリントを改善し、既存のクラスデータ共有(”CDS”)機能を拡張して、アプリケーションクラスを共有アーカイブに配置するのに役立ちます。JVMは起動時にいくつかの予備的なステップを実行しますが、その中の一つはクラスのメモリへのロードです。複数のクラスを持つ複数のJARファイルがある場合、最初のリクエストの遅延が明らかになります。これは、ブート時間が重要なサーバーレスアーキテクチャでは問題となります。アプリケーションの起動時間を短縮するために、アプリケーションクラスデータ共有を使用することができます。アイデアは、異なるJavaプロセス間で共通のクラスメタデータを共有することによってフットプリントを減らすことです。これは以下の3つのステップで達成できます:アーカイブするクラスの決定:アーカイブするファイルのリストを作成するためにJavaランチャーを使用します。以下のパラメータを使用することで実現できます:
$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld
AppCDSアーカイブの作成:アプリケーションCDSに使用するファイルのリストのアーカイブを作成するためにJavaランチャーを使用します。以下のパラメータを使用することで実現できます:
$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst -XX:SharedArchiveFile=hello.jsa -cp hello.jar
AppCDSアーカイブの使用:アプリケーションCDSを使用するためには、以下のパラメータを使用してJavaランチャーを実行します。
$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld
G1 ガベージコレクタはJDK 9でデフォルトになりました。G1ガベージコレクタは、完全なガベージコレクションを回避しますが、収集のための同時スレッドがメモリを十分に高速に回復できない場合、ユーザーの体験に影響が出ます。この変更により、完全なGCが並列化され、G1最悪のケースのレイテンシが改善されます。この変更の一部として、G1コレクタのマークスイープコンパクトアルゴリズムが並列化され、収集のための同時スレッドがメモリを十分に高速に回復できない場合にトリガされます。25. ### ガベージコレクタインターフェース(JEP 304)
このJEPは将来志向の変更です。異なるガベージコレクタのコード分離を改善し、共通のガベージコレクタインターフェースを導入します。この変更により、内部GCコードのモジュラリティが向上します。既存のコードベースを変更せずに新しいGCを追加するのに役立ちます。また、以前のGCの削除やハウスキーピングにも役立ちます。26. ### 追加のUnicode言語タグ拡張(JEP 314)
この機能は、java.util.Localeおよび関連するAPIを拡張し、BCP 47言語タグの追加のUnicode拡張を実装します。Java SE 9では、サポートされているBCP 47 U言語タグ拡張は「ca」と「nu」です。このJEPでは、以下の追加の拡張のサポートが追加されます:
- cu(通貨タイプ)
- fw(週の最初の日)
- rg(地域の上書き)
- tz(タイムゾーン)
これらの追加拡張をサポートするために、さまざまなAPIに変更が加えられ、Uまたは追加拡張に基づいた情報を提供します。
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
OpenJDKを促進し、コミュニティユーザーに魅力的なものにするために、この機能はJDKにデフォルトのルート認証機関(CA)証明書のセットを提供します。これにより、OracleとOpenJDKのバイナリは機能的に同じになります。TLSなどの重要なセキュリティコンポーネントは、OpenJDKビルドでデフォルトで動作するようになります。30. ### スレッドローカルハンドシェイク(JEP 312)
これはパフォーマンスを向上させるための内部JVM機能です。ハンドシェイク操作は、スレッドがセーフポイント状態にある間に各Javaスレッドに対して実行されるコールバックです。コールバックは、スレッド自体によって実行されるか、スレッドをブロックされた状態にしているVMスレッドによって実行されます。この機能により、グローバルなVMセーフポイントを実行せずにスレッド上でコールバックを実行する方法が提供されます。個々のスレッドを停止することができ、すべてのスレッドまたはいずれのスレッドも停止しないことが可能になります。31. ### 代替メモリデバイス上のヒープ割り当て(JEP 316)
アプリケーションはメモリを多く必要とするようになり、クラウドネイティブアプリケーション、インメモリデータベース、ストリーミングアプリケーションの増加があります。これらのサービスに対応するために、さまざまなメモリアーキテクチャが利用可能です。この機能は、HotSpot VMの能力を向上させ、ユーザーが指定したNV-DIMMなどの代替メモリデバイスにJavaオブジェクトヒープを割り当てることができます。このJEPは、DRAMと同じセマンティクス(アトミック操作を含む)を持つ代替メモリデバイスを対象としており、既存のアプリケーションコードを変更することなくオブジェクトヒープでDRAMの代わりに使用することができます。32. ### ネイティブヘッダ生成ツール(javah)の削除(JEP 313)
この変更は、JDKからjavahツールを削除するための整理作業です。ツールの機能はJDK 8の一部としてjavac
に追加され、ネイティブヘッダファイルをコンパイル時に書く能力を提供するため、javah
は不要になりました。35. ### JDKフォレストの統合(JEP 296)
これまでJDKコードベースにはさまざまなMercurialリポジトリが存在しました。異なるリポジトリはいくつかの利点を提供していましたが、さまざまな運用上の問題もありました。この変更の一環として、JDKフォレストの多数のリポジトリが統合され、開発を簡素化・効率化するために単一のリポジトリに統合されました。36. ### API変更
Java 10はAPIを追加および削除しました(Yes、タイプミスではありません)。 Java 9では、将来のリリースで削除される予定の特定のAPIに強化された非推奨が導入されました。 削除されたAPI:削除されたAPIはこちらで確認できます。 追加されたAPI:Java 10には73の新しいAPIが追加されました。追加されたAPIおよび比較はこちらで確認できます。いくつかの追加点を見てみましょう:
- リスト、マップ、およびセットインターフェースには、静的なcopyOf(Collection)メソッドが追加されました。これにより、提供されたエントリを含む変更不可能なリスト、マップ、またはセットが返されます。リストの場合、指定されたリストが後で変更された場合、返されるリストはそのような変更を反映しません。
- Optionalおよびそのプリミティブバリエーションには、メソッドorElseThrow()が追加されます。これはget()とまったく同じですが、javaドキュメントではget()よりも優先される代替手段として述べられています。
- Collectorsクラスには、変更不可能なコレクション(セット、リスト、マップ)を収集するためのさまざまなメソッドが追加されます。
List actors = new ArrayList<>();
actors.add("Jack Nicholson");
actors.add("Marlon Brando");
System.out.println(actors); // prints [Jack Nicholson, Marlon Brando]
// 新しいAPIが追加されました-リストからUnModifiableリストを作成します。
List copyOfActors = List.copyOf(actors);
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
// copyOfActors.add("Robert De Niro");は
// UnsupportedOperationExceptionを生成しますを生成します
actors.add("Robert De Niro");
System.out.println(actors);// prints [Jack Nicholson, Marlon Brando, Robert De Niro]
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
String str = "";
Optional name = Optional.ofNullable(str);
// 新しいAPIが追加されました- get()メソッドよりも優先されるオプションです
name.orElseThrow(); // same as name.get()
// 新しいAPIが追加されました- Collectors.toUnmodifiableList
List collect = actors.stream().collect(Collectors.toUnmodifiableList());
// collect.add("Tom Hanks"); //
// UnsupportedOperationExceptionを生成しますを生成します
結論
この記事では、Java 10のさまざまな新機能の追加を見てきました。ここで重要な点を見逃していると思うものがあれば、コメントでお知らせください。いつものように、GitHubで完全なコードを確認できます。こちら。
Source:
https://www.digitalocean.com/community/tutorials/java-10-features