JavaFXプロジェクトを8 Javaバージョンから11バージョンにアップグレードしようとしています。 「run」Gradleタスクを使用すると機能します( Openjfxチュートリアルに従いました )が、ビルド(「jar」Gradleタスクを使用)および実行(「Java -jar」を使用)するとjarファイルには、「エラー:JavaFXランタイムコンポーネントがありません。このアプリケーションを実行するために必要です」というメッセージが表示されます。
これが私のbuild.gradleファイルです:
group 'Project'
version '1.0'
apply plugin: 'Java'
sourceCompatibility = 1.11
repositories {
mavenCentral()
}
def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) {
platform = 'win'
} else if (currentOS.isLinux()) {
platform = 'linux'
} else if (currentOS.isMacOsX()) {
platform = 'mac'
}
dependencies {
compile "org.openjfx:javafx-base:11:${platform}"
compile "org.openjfx:javafx-graphics:11:${platform}"
compile "org.openjfx:javafx-controls:11:${platform}"
compile "org.openjfx:javafx-fxml:11:${platform}"
}
task run(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = "project.Main"
}
jar {
manifest {
attributes 'Main-Class': 'project.Main'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls,javafx.fxml'
]
}
}
run {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls,javafx.fxml'
]
}
}
私が何をすべきか知っていますか?
誰かが興味があるなら、JavaFX11プロジェクト用のjarファイルを作成する方法を見つけました(Java 9モジュール)。 Windowsでのみテストしました(アプリケーションがLinuxにも対応している場合、LinuxでJavaFX jarを取得するにはLinuxでも同じ手順を実行する必要があると思います)。
「Project.main」モジュール(Gradleプロジェクトを作成したときにIDEAで作成)があります。
src
+-- main
| +-- Java
| +-- main
| +-- Main.Java (from the "main" package, extends Application)
| +-- module-info.Java
build.gradle
settings.gradle
...
Module-info.Javaファイル:
module Project.main {
requires javafx.controls;
exports main;
}
Build.gradleファイル:
plugins {
id 'Java'
}
group 'Project'
version '1.0'
ext.moduleName = 'Project.main'
sourceCompatibility = 1.11
repositories {
mavenCentral()
}
def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) {
platform = 'win'
} else if (currentOS.isLinux()) {
platform = 'linux'
} else if (currentOS.isMacOsX()) {
platform = 'mac'
}
dependencies {
compile "org.openjfx:javafx-base:11:${platform}"
compile "org.openjfx:javafx-graphics:11:${platform}"
compile "org.openjfx:javafx-controls:11:${platform}"
}
task run(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = "main.Main"
}
jar {
inputs.property("moduleName", moduleName)
manifest {
attributes('Automatic-Module-Name': moduleName)
}
}
compileJava {
inputs.property("moduleName", moduleName)
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls'
]
classpath = files()
}
}
task createJar(type: Copy) {
dependsOn 'jar'
into "$buildDir/libs"
from configurations.runtime
}
Settings.gradleファイル:
rootProject.name = 'Project'
そしてGradleコマンド:
#Run the main class
gradle run
#Create the jars files (including the JavaFX jars) in the "build/libs" folder
gradle createJar
#Run the jar file
cd build/libs
Java --module-path "." --module "Project.main/main.Main"
Java/JavaFX 11では、shadow/fat jarは機能しません。
あなたが読むことができるように ここ :
このエラーは、Java.baseモジュールの
Sun.launcher.LauncherHelper
から発生します。これは、メインアプリがApplication
を拡張し、mainメソッドを持っているためです。その場合、LauncherHelper
は、名前付きモジュールとして存在するjavafx.graphicsモジュールをチェックします。
Optional<Module> om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
そのモジュールが存在しない場合、起動は中止されます。したがって、この場合、クラスパス上のJavaFXライブラリをjarとして使用することはできません。
さらに、すべてのJavaFX 11 jarには、ルートレベルにmodule-info.class
ファイルがあります。
すべてのjarコンテンツを1つのファットjarにバンドルすると、同じ名前と同じ場所のファイルはどうなりますか?ファットjarがそれらすべてを保持している場合でも、それは単一のモジュールとしてどのように識別されますか?
これをサポートする要求がありますが、まだ対処されていません: http://openjdk.Java.net/projects/jigsaw/spec/issues/#MultiModuleExecutableJARs
複数のモジュールを含む実行可能なモジュール式「uber-JAR」を作成し、モジュールの識別と境界を保持する手段を提供して、アプリケーション全体を単一のアーティファクトとして出荷できるようにします。
シャドウプラグインは、すべてのother依存関係を1つのjarにバンドルするのに意味がありますが、やはり次のようなものを実行する必要があります。
Java --module-path <path-to>/javafx-sdk-11/lib \
--add modules=javafx.controls -jar my-project-ALL-1.0-SNAPSHOT.jar
これは、結局のところ、JavaFX SDKを(プラットフォームごとに)インストールして、Maven CentralからJavaFX依存関係を使用していたjarを実行する必要があることを意味します。
別の方法として、jlink
を使用して軽量JREを作成することもできますが、アプリはモジュール式である必要があります。
また、Javapackagerを使用して、プラットフォームごとにインストーラーを生成できます。 http://openjdk.Java.net/jeps/34 を参照してください。これにより、Java 12のパッケージャーが生成されます。
最後に、Java 11/JavaFX 11で動作するJavapackagerの実験バージョンがあります。 http://mail.openjdk.Java.net/pipermail/openjfx-dev/2018-September /022500.html
編集
Javaランチャーはメインクラスがjavafx.application.Application
を拡張するかどうかをチェックするため、その場合はJavaFXランタイムをモジュールとして(jarとしてではなく)使用できる必要があるため、動作させるための可能な回避策は次のとおりです。プロジェクトのメインクラスになるnewメインクラスを追加し、そのクラスがJavaFXアプリケーションクラスを呼び出すクラスになります。
Applicationクラスを持つjavafx11
パッケージがある場合:
public class HelloFX extends Application {
@Override
public void start(Stage stage) {
String javaVersion = System.getProperty("Java.version");
String javafxVersion = System.getProperty("javafx.version");
Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
Scene scene = new Scene(new StackPane(l), 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
次に、このクラスをそのパッケージに追加する必要があります。
public class Main {
public static void main(String[] args) {
HelloFX.main(args);
}
}
そして、ビルドファイルで:
mainClassName='javafx11.Main'
jar {
manifest {
attributes 'Main-Class': 'javafx11.Main'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
これで実行できます:
./gradlew run
または
./gradlew jar
Java -jar build/libs/javafx11-1.0-SNAPSHOT.jar
最終的な目標は、モジュールパス上で名前付きモジュールとしてJavaFXモジュールを使用することです。これは、アプリケーションをテストするための迅速/ ugい回避策のように見えます。配布については、上記のソリューションを引き続き提案します。