1. 概要

このチュートリアルでは、Javaエコシステムの新しいバージョンである Java SE 17 に関連するニュースについて説明します。これには、新機能とそのリリースプロセスの変更、LTSサポート、ライセンス。

2. JEPのリスト

まず、Java開発者の日常業務に何が影響するかについて話しましょう。

2.1. 常に厳密な浮動小数点セマンティクスを復元する( JEP 306

このJEPは主に科学的なアプリケーション向けであり、浮動小数点演算を一貫して厳密にします。 デフォルトの浮動小数点演算はstrictまたはstrictfpであり、どちらもすべてのプラットフォームでの浮動小数点計算から同じ結果を保証します。

Java 1.2より前では、strictfpの動作もデフォルトの動作でした。 ただし、ハードウェアの問題により、アーキテクトが変更され、このような動作を再度有効にするには、キーワードstrictfpが必要でした。 したがって、このキーワードを使用する必要はもうありません。

2.2. 強化された疑似乱数ジェネレーター( JEP 356

また、より特殊なユースケースに関連して、JEP 356は、疑似乱数ジェネレーター(PRNG)の新しいインターフェイスと実装を提供します。

したがって、さまざまなアルゴリズムを交換可能に使用する方が簡単であり、ストリームベースのプログラミングのサポートも向上します。

public IntStream getPseudoInts(String algorithm, int streamSize) {
    // returns an IntStream with size @streamSize of random numbers generated using the @algorithm
    // where the lower bound is 0 and the upper is 100 (exclusive)
    return RandomGeneratorFactory.of(algorithm)
            .create()
            .ints(streamSize, 0,100);
}

java.util.Random SplittableRandom SecureRandom などのレガシーランダムクラスは、新しいRandomGeneratorインターフェイスを拡張するようになりました。

2.3. 新しいmacOSレンダリングパイプライン( JEP 382

このJEPは、AppleがSwingGUIで内部的に使用されるOpenGLAPI(macOS 10.14)を廃止したため、macOS用のJava2D内部レンダリングパイプラインを実装します。 新しい実装はAppleMetalAPIを使用しており、内部エンジンを除いて、既存のAPIに変更はありませんでした。

2.4. macOS / AArch64 ポート( JEP 391

Appleは、コンピュータラインをX64からAArch64に移行する長期計画を発表しました。 このJEPは、macOSプラットフォームのAArch64で実行するようにJDKを移植します。

2.5. 削除のためのアプレットAPIの非推奨( JEP 398

これは、アプレットAPIを使用して開発キャリアを開始した多くのJava開発者にとっては悲しいことかもしれませんが、多くのWebブラウザはすでにJavaプラグインのサポートを削除しています。 APIが無関係になったため、このバージョンでは、バージョン9以降非推奨としてマークされていても、削除のマークが付けられました。

2.6. JDK内部を強力にカプセル化( JEP 403

JEP 403は、フラグ –illegal-access を削除するため、JDK内部を強力にカプセル化するためのもう1つのステップを表しています。 プラットフォームはフラグを無視し、フラグが存在する場合、コンソールはフラグの中止を通知するメッセージを発行します。

この機能により、 sun.misc.Unsafe などの重要なAPIを除き、JDKユーザーが内部APIにアクセスできなくなります。

2.7. スイッチのパターンマッチング(プレビュー)( JEP 406

これは、 switch の式とステートメントのパターンマッチングを強化することにより、パターンマッチングに向けたもう1つのステップです。 これらの表現を定義するために必要な定型文を減らし、言語の表現力を向上させます。

新機能の2つの例を見てみましょう。


static record Human (String name, int age, String profession) {}

public String checkObject(Object obj) {
    return switch (obj) {
        case Human h -> "Name: %s, age: %s and profession: %s".formatted(h.name(), h.age(), h.profession());
        case Circle c -> "This is a circle";
        case Shape s -> "It is just a shape";
        case null -> "It is null";
        default -> "It is an object";
    };
}

public String checkShape(Shape shape) {
    return switch (shape) {
        case Triangle t && (t.getNumberOfSides() != 3) -> "This is a weird triangle";
        case Circle c && (c.getNumberOfSides() != 0) -> "This is a weird circle";
        default -> "Just a normal shape";
    };
}

2.8. RMIアクティベーションを削除します( JEP 407

バージョン15で削除のマークが付けられたこのJEPは、バージョン17でプラットフォームからRMIアクティベーションAPIを削除しました。

2.9. 封印されたクラス( JEP 409

封印されたクラスはProjectAmber の一部であり、このJEPは、JDKバージョン15および16[でプレビューモードで使用可能でしたが、言語に新しい機能を正式に導入します。 X201X]。

この機能は、封印されたコンポーネントを拡張または実装できる他のクラスまたはインターフェースを制限します。 JEP 406と組み合わせたパターンマッチングに関連する別の改善を示すことで、タイプ、キャスト、およびアクトコードパターンのより洗練されたよりクリーンな検査が可能になります。

実際の動作を見てみましょう。


int getNumberOfSides(Shape shape) {
    return switch (shape) {
        case WeirdTriangle t -> t.getNumberOfSides();
        case Circle c -> c.getNumberOfSides();
        case Triangle t -> t.getNumberOfSides();
        case Rectangle r -> r.getNumberOfSides();
        case Square s -> s.getNumberOfSides();
    };
}

2.10. 実験的なAOTおよびJITコンパイラ( JEP 410 )を削除します

実験的な機能として、それぞれJDK9とJDK10に導入された、Ahead-Of-Time(AOT)コンパイル( JEP 295 )とGraalVMのJust-In-Time(JIT)コンパイラ( JEP-317 )は、メンテナンスコストの高い機能でした。

一方で、彼らは重要な採用をしていませんでした。 そのため、このJEPはそれらをプラットフォームから削除しましたが、開発者はGraalVMを使用してそれらを引き続き活用できます。

2.11. 削除するSecurityManagerの非推奨( JEP 411

クライアント側のJavaコードを保護することを目的としたセキュリティマネージャは、関連性がなくなったために削除のマークが付けられたもう1つの機能です。

2.12. 外部関数およびメモリAPI(インキュベーター)( JEP 412

Foreign Function and Memory APIを使用すると、Java開発者はJVMの外部からコードにアクセスし、ヒープ外のメモリを管理できます。 目標は、 JNI API を置き換え、古いものと比較してセキュリティとパフォーマンスを向上させることです。

このAPIは、 Project Panama によって開発された別の機能であり、JEP 393 389 383 、および 383 によって進化し、廃止されました。 X159X]370。

この機能を使用すると、JavaクラスからCライブラリを呼び出すことができます。


private static final SymbolLookup libLookup;

static {
    // loads a particular C library
    var path = JEP412.class.getResource("/print_name.so").getPath();
    System.load(path);
    libLookup = SymbolLookup.loaderLookup();
}

まず、APIを介して呼び出したいターゲットライブラリをロードする必要があります。

次に、ターゲットメソッドのシグネチャを指定し、最後にそれを呼び出す必要があります。


public String getPrintNameFormat(String name) {

    var printMethod = libLookup.lookup("printName");

    if (printMethod.isPresent()) {
        var methodReference = CLinker.getInstance()
            .downcallHandle(
                printMethod.get(),
                MethodType.methodType(MemoryAddress.class, MemoryAddress.class),
                FunctionDescriptor.of(CLinker.C_POINTER, CLinker.C_POINTER)
            );

        try {
            var nativeString = CLinker.toCString(name, newImplicitScope());
            var invokeReturn = methodReference.invoke(nativeString.address());
            var memoryAddress = (MemoryAddress) invokeReturn;
            return CLinker.toJavaString(memoryAddress);
        } catch (Throwable throwable) {
            throw new RuntimeException(throwable);
        }
    }
    throw new RuntimeException("printName function not found.");
}

2.13. ベクターAPI(セカンドインキュベーター)( JEP 414

Vector APIは、SIMD(単一命令、複数データ)タイプの操作を処理します。つまり、さまざまな命令のセットが並行して実行されます。 ベクトル命令をサポートし、パイプラインなどの命令の実行を可能にする専用のCPUハードウェアを活用します。

その結果、新しいAPIにより、開発者は基盤となるハードウェアの可能性を活用して、より効率的なコードを実装できるようになります。

この操作の日常的な使用例は、科学代数線形アプリケーション、画像処理、文字処理、および重い算術アプリケーション、または複数の独立したオペランドに操作を適用する必要があるアプリケーションです。

APIを使用して、簡単なベクトル乗算の例を示しましょう。


public void newVectorComputation(float[] a, float[] b, float[] c) {
    for (var i = 0; i < a.length; i += SPECIES.length()) {
        var m = SPECIES.indexInRange(i, a.length);
        var va = FloatVector.fromArray(SPECIES, a, i, m);
        var vb = FloatVector.fromArray(SPECIES, b, i, m);
        var vc = va.mul(vb);
        vc.intoArray(c, i, m);
    }
}

public void commonVectorComputation(float[] a, float[] b, float[] c) {
    for (var i = 0; i < a.length; i ++) {
        c[i] = a[i] * b[i];
    }
}

2.14. コンテキスト固有の逆シリアル化フィルター( JEP 415

JEP 290 は、JDK 9で最初に導入され、多くのセキュリティ問題の一般的なソースである信頼できないソースからの着信シリアル化データを検証できるようにしました。 この検証はJVMレベルで行われるため、セキュリティと堅牢性が向上します。

JEP 415を使用すると、アプリケーションは、JVMレベルで定義されたコンテキスト固有の動的に選択された逆シリアル化フィルターを構成できます。 各逆シリアル化操作は、そのようなフィルターを呼び出します。

3. LTSの定義

変更はコードだけにとどまらず、プロセスも変更されています。

Javaプラットフォームのリリースには、長く不正確であるという広く知られた歴史があります。 リリースの間隔が3年になるように設計されているにもかかわらず、多くの場合、4年のプロセスになりました。

さらに、イノベーションと迅速な対応が義務付けられた市場の新しいダイナミクスを考慮して、プラットフォームの進化を担当するチームは、新しい現実に適応するためにリリースのリズムを変更することを決定しました。

その結果、Java 10(2018年3月20日リリース)以降、新しい6か月の機能リリースモデルが採用されました。

3.1. 6か月の機能リリースモデル

新しい6か月の機能リリースモデルにより、プラットフォーム開発者は準備ができたときに機能をリリースできます。これにより、機能をリリースにプッシュするプレッシャーがなくなります。 そうしないと、プラットフォームのユーザーが機能を利用できるようになるまで3〜4年待つ必要があります。

新しいモデルは、ユーザーとプラットフォームのアーキテクト間のフィードバックサイクルも改善します。 これは、機能をインキュベーションモードで利用可能にし、いくつかの対話の後にのみ一般的な使用のためにリリースできるためです。

3.2. LTSモデル

エンタープライズアプリケーションはJavaを広く使用しているため、安定性が重要です。 さらに、これらすべてのバージョンのパッチ更新をサポートおよび提供し続けるにはコストがかかります。

このため、長期サポート(LTS)バージョンが作成され、ユーザーに拡張サポートが提供されました。 そのため、このようなバージョンは、バグ修正、パフォーマンスの向上、セキュリティパッチにより、当然、より安定して安全になります。 Oracleの場合、このサポートは通常8年間続きます。

リリースモデルの変更が導入されて以来、LTSバージョンはJava SE 11(2018年9月にリリース)とJava SE 17(2021年9月にリリース)でした。 それにもかかわらず、バージョン17はモデルに何か新しいものをもたらしました。 つまり、 LTSバージョン間の間隔は3年ではなく2年になり、Java 21(2023年9月に予定)はおそらく次のLTSになります。

言及する価値のあるもう1つのポイントは、このリリースモデルは新しいものではないということです。 それは恥知らずにコピーされ、Mozilla Firefox、Ubuntuなど、モデルがそれ自体を証明した他のプロジェクトから採用されました。

4. 新しいリリースプロセス

この記事は、プロセスのすべての変更について説明しているため、 JEP3に基づいています。 詳しくはご確認ください。 ここでは、その簡潔な要約を提供しようとします。

上記の新しいモデルと、プラットフォームの継続的な開発および新しい6か月のリリースリズム(通常は6月と12月)を組み合わせると、Javaの動きは速くなります。 JDKの開発チームは、次に説明するプロセスに従って、次の機能リリースのリリースサイクルを開始します。

プロセスは、メインラインのフォークから始まります。 次に、安定化リポジトリJDK / JDK $ N(たとえば、 JDK17 )で開発が続行されます。 そこでは、リリースの安定化に焦点を当てた開発が続けられています。

プロセスを深く掘り下げる前に、いくつかの用語を明確にしましょう。

  • バグ:このコンテキストでは、バグはチケットまたはタスクを意味します。
    • Current :これらは、現在のバージョン(リリースされようとしている新しいバージョン)に関連する実際のバグか、このバージョンにすでに含まれている新機能の調整(新しいJEP)のいずれかです。
    • ターゲット:古いバージョンに関連しており、この新しいバージョンで修正または対処される予定です。
  •  優先度:P1からP5までの範囲で、P1が最も重要であり、重要度はP5まで徐々に低下します。

4.1. 新しいフォーマット

安定化プロセスは、次の3か月間進行します。

  • JDK / JDK $ Nリポジトリはリリースブランチのように機能し、この時点では、新しいJEPの新しいJEPはリポジトリに入りません。
  • 次に、このリポジトリの開発は安定化され、他の開発が継続されるメインラインに移植されます。
  • ランプダウンフェーズ1(RDP 1):4〜5週間続きます。 開発者は、すべての電流P4-P5とターゲットのP1-P3を削除します(遅延修正、または拡張によって異なります)。 これは、P5+テスト/ドキュメントのバグと対象となるP3+コードのバグがオプションであることを意味します。
  • ランプダウンフェーズ2(RDP 2):3〜4週間続きます。 現在、すべての電流P3-P5とターゲットのP1-P3を延期しています(遅延修正、または拡張によって異なります)。
  • 最後に、チームはリリース候補ビルドを公開し、一般に公開します。 このフェーズは2〜5週間続き、現在のP1修正のみが対処されます(修正を使用)。

これらのサイクルがすべて終了すると、新しいリリースが一般提供(GA)バージョンになります。

5. 次は何ですか?

JDKアーキテクトは、プラットフォームの最新化を目的とした多くのプロジェクトに引き続き取り組んでいます。 目標は、より優れた開発エクスペリエンスと、より堅牢でパフォーマンスの高いAPIを提供することです。

結果として、JDK 18は今から6か月後にリリースされるはずですが、このバージョンには重大な変更や破壊的な変更が含まれている可能性は低いです。 公式のOpenJDKプロジェクトポータルで、このバージョンを対象とする提案されたJEPのリストをたどることができます。

現在および将来のバージョンに影響を与えるもう1つの関連ニュースは、Oracle JDKディストリビューション(またはホットスポット)に適用される新しい無料の契約条件ライセンスです。 ほとんどの場合、オラクルは本番環境およびその他の環境に無料で配布を提供しますが、いくつかの例外があります。 繰り返しになりますが、リンクを参照してください。

前述のように、新しいプロセスは次のLTSバージョンをバージョン21にすることを目標としており、2023年9月までにリリースする予定です。

6. 結論

この記事では、新しいJava 17バージョンに関するニュースを見て、最近の開発、新機能、サポート定義、およびリリースサイクルプロセスについて説明しました。

いつものように、この記事で使用されているすべてのコードサンプルは、GitHubから入手できます。