少しはまったのでメモ。
Gradle org.beryx.jlink プラグインで、ランタイムがバンドルされたアプリケーションを作成する場合、以下のような build.gradle.kts を作成する。
plugins {
application
id("org.beryx.jlink") version "3.0.1"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
mainClass = "example.App"
mainModule = "example.app"
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
jlink {
launcher {
name = "app"
}
jpackage {
skipInstaller = true
}
}
以下のようにすれば、実行イメージが作成できる。
./gradlew jlink
イメージ内にバッチファイルが作成されるので、以下のように実行できる。
app\build\image\bin\app.bat
以下のようにすれば、exe ファイルが作成できる。
./gradlew jpackage
exe ファイルを実行すると、
app\build\jpackage\app\app.exe
何事もなく終了するか、以下のような「Failed to launch JVM」エラーとなる。

Windows のコンソールアプリケーションには以下のオプション指定が必要なため。

org.beryx.jlink プラグインの場合は imageOptions = listOf("--win-console") を指定する必要がある。
以下のようになる。
plugins {
application
id("org.beryx.jlink") version "3.0.1"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
mainClass = "example.App"
mainModule = "example.app"
}
tasks.named<Test>("test") {
useJUnitPlatform()
}
jlink {
launcher {
name = "app"
}
jpackage {
imageOptions = listOf("--win-console")
skipInstaller = true
}
}
なお、skipInstaller を指定しない場合は、インストーラが作成される。ただし、WiX を別途インストールしておく必要がある。