ビルド

このセクションでは、Spring Shell アプリケーションを構築する方法について説明します。

スターター

  1. Spring Shell スターター

名前 説明

spring-shell-starter

基本 Spring Shell モジュール

spring-shell-starter-jansi

JLine ジャンシプロバイダー

spring-shell-starter-jni

JLine jni プロバイダーを使用

spring-shell-starter-jna

JLine jna プロバイダー

spring-shell-starter-ffm

JLine ffm プロバイダー (JDK22 以上が必要)

spring-shell-starter-test

Spring Shell テストサポート

ターミナルプロバイダー

プログラムが実行されている基盤となるターミナルとのやり取りは、従来、比較的複雑なプロセスでしたが、すべてがテキストだけなので、それほど多くのことは起こっていないように見えるかもしれません。

昔の手動型ライターやマトリックスプリンターを覚えていますか ? カーソルがある場所に文字が出力され、別の位置に出力する場合はカーソルを移動する必要があります。簡単に言えば、現在のターミナルエミュレーターはこのように動作します。

既存のターミナルエミュレーター環境にアクセスして理解を深めるために、JLine は独自の共有ライブラリを介してネイティブコードを使用できます。JLine は存在するプロバイダーを検出し、使用するプロバイダーを選択します。従来、jansijnijna の 3 つのプロバイダーがあり、すべて同じ機能を提供する必要があります。

当社のスターターを使用すると、これらの JLine プロバイダーのいくつかを具体的に選択できます。

FFM

JDK22 では、プレビューから外部関数およびメモリ API がリリースされ、JNI の代替として、より優れた安全なネイティブ API を提供するものになる予定です。

3.4.x から、Spring Shell アプリケーションを JLine ffm ターミナルプロバイダーでコンパイルするためのサポートを追加しました。これは明らかに、アプリケーションを JDK22+ で実行する必要があることを意味します。新しい JDK 中間リリースは 6 か月ごとに、長期サポート (LTS) リリースは 2 年ごとにあります。Spring Shell が Spring Framework と連携できる既存の LTS リリースが出るまでは、最新の JDK リリースを使用します。明らかに、これは ffm を使用することを選択した場合、都合の悪いときに JDK をアップグレードする必要がある可能性があることを意味します。また、JLine 自体が ffm 部分をコンパイルするために使用する JDK バージョンにも縛られます。

FFM 自体が、その一部が使用されると、jvm に警告を出力させます。これらの警告は、干渉して多少の混乱を引き起こす可能性があるため、ターミナルアプリケーションでは明らかに迷惑です。将来の JDK バージョンでは、これらの警告は古い JNI モジュールにも追加され、ある時点でこれらの警告はハードエラーに変更されます。ユーザーは、これらのネイティブの「安全でない」部分を手動で有効にする必要があります。

コマンドラインでの JVM オプションは次のとおりです。

--enable-native-access=ALL-UNNAMED

jar ファイルがある場合は、その META-INF/MANIFEST.MF にこの設定を含めることができます。

Enable-Native-Access: ALL-UNNAMED

ビルド中に追加できるもの(gradle を使用する場合など):

tasks.named("bootJar") {
    manifest {
        attributes 'Enable-Native-Access': 'ALL-UNNAMED'
    }
}
JDK でネイティブ部分を有効にする場合、JLine は積極的にこれに対するチェックを行っており、ネイティブアクセスが有効になっていない場合はエラーをスローします。

ネイティブサポート

Spring Shell アプリケーションを GraalVM バイナリにコンパイルするためのサポートは、主に Spring Framework および Spring Boot から提供され、機能は AOT と呼ばれます。アヘッドオブタイムとは、コンパイル時にアプリケーションコンテキストが準備され、GraalVM 生成の準備が整うことを意味します。

フレームワーク Spring Shell からの AOT 機能上に構築する独自の GraalVM 構成があり、バイナリに何が存在すべきかのヒントを提供します。通常、問題は、GraalVM 関連の構成がまだ含まれていないか、それらの構成が不完全なサードパーティライブラリから発生します。

サードパーティのライブラリに不足しているヒントを提供する GraalVM Reachability Metadata Repository を使用する必要があります。また、GraalVM をインストールし、それを指す JAVA_HOME  が必要です。

gradle の場合、graalvm のネイティブプラグインを追加し、メタデータリポジトリを構成します。

plugins {
	id 'org.graalvm.buildtools.native' version '0.9.16'
}

graalvmNative {
	metadataRepository {
        enabled = true
	}
}

gradle ビルドが ./gradlew nativeCompile で実行されると、build/native/nativeCompile ディレクトリにバイナリを取得する必要があります。

maven の場合、spring-boot-starter-parent を親として使用すると、コンパイルに使用できる native プロファイルが得られます。メタデータリポジトリを構成する必要があります

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
                <configuration>
                    <metadataRepository>
                        <enabled>true</enabled>
                    </metadataRepository>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>
spring-boot-starter-parent に依存している場合は、最新に保たれている native-maven-plugin バージョンを管理します。

maven ビルドが ./mvnw native:compile -Pnative で実行されると、target ディレクトリにバイナリを取得する必要があります。

すべてがうまくいった場合、jvm を介して Boot アプリケーション jar を実行する代わりに、このバイナリをそのまま実行できます。