簡単な要約では、次のいずれかを実行できます。
--module-path
およびを介してJavaFXモジュールを含める--add-modules
ホセの答えのように。
または
JavaFXライブラリをプロジェクトに追加したら(手動またはmaven / gradleインポートを介して)、module-info.java
この回答で指定されているものと同様のファイルを追加します。(このソリューションはアプリをモジュール化するため、他のライブラリを使用する場合は、module-info.java
ファイル内にモジュールを要求するステートメントも追加する必要があることに注意してください)。
この答えは、ホセの答えを補足するものです。
状況はこれです:
- 最近のJavaバージョン(13など)を使用しています。
- MavenプロジェクトとしてJavaFXアプリケーションがあります。
- Mavenプロジェクトでは、Joseの回答に従って、JavaFXプラグインが構成され、JavaFX依存関係が設定されています。
- Applicationを拡張するメインクラスのソースコードに移動し、それを右クリックして実行しようとします。
- あなたは、取得
IllegalAccessError
アプリを起動しようとすると、「無名のモジュール」を含みます。
IllegalAccessError
Intellij IdeaからJavaFXアプリを実行しようとしたときに生成されるスタックトレースの抜粋:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x45069d0e) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x45069d0e
at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)
at org.jewelsea.demo.javafx.springboot.Main.start(Main.java:13)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application org.jewelsea.demo.javafx.springboot.Main
OK、今あなたはちょっと立ち往生していて、何が起こっているのか見当がつかない。
実際に起こったことはこれです:
- MavenはアプリケーションのJavaFX依存関係を正常にダウンロードしたため、依存関係を個別にダウンロードしたり、JavaFXSDKやモジュールディストリビューションなどをインストールしたりする必要はありません。
- Ideaはモジュールをプロジェクトへの依存関係として正常にインポートしたため、すべてが正常にコンパイルされ、すべてのコード補完とすべてが正常に機能します。
だから、すべてが大丈夫なはずです。ただし、アプリケーションを実行すると、リフレクションを使用してアプリケーションクラス(launchを呼び出すとき)とFXMLコントローラークラス(FXMLをロードするとき)のインスタンスをインスタンス化しようとすると、JavaFXモジュールのコードが失敗します。助けがなければ、この反射の使用は場合によっては失敗し、あいまいなものを生成する可能性がありますIllegalAccessError
ます。これは、明示的に許可しない限り、他のモジュールのコードがクラスでリフレクションを使用できないようにするJavaモジュールシステムのセキュリティ機能によるものです(JavaFXアプリケーションランチャーとFXMLLoaderはどちらも、機能するために現在の実装でリフレクションを必要とします)正しく)。
ここで、この質問に対する他のいくつかの回答(参照module-info.java
)が登場します。
それでは、Javaモジュールのクラッシュコースを受講しましょう。
重要な部分はこれです:
4.9。開く
プライベートタイプの反映を許可する必要があるが、すべてのコードを公開したくない場合は、opensディレクティブを使用して特定のパッケージを公開できます。
ただし、これによりパッケージが全世界に開かれることを忘れないでください。それが必要なものであることを確認してください。
module my.module { opens com.my.package; }
したがって、パッケージを全世界に公開したくない場合は、次のことができます。
4.10。開く…へ
さて、リフレクションは時々素晴らしいですが、それでもカプセル化から得られる限りのセキュリティが必要です。この場合、opens…toディレクティブを使用して、事前に承認されたモジュールのリストに対してパッケージを選択的に開くことができます。
module my.module {com.my.packageをmoduleOne、moduleTwoなどに開きます。}
したがって、次のようなsrc / main / java /module-info.javaクラスを作成することになります。
module org.jewelsea.demo.javafx.springboot {
requires javafx.fxml;
requires javafx.controls;
requires javafx.graphics;
opens org.jewelsea.demo.javafx.springboot to javafx.graphics,javafx.fxml;
}
ここで、org.jewelsea.demo.javafx.springboot
はJavaFXApplicationクラスとJavaFXControllerクラスを含むパッケージの名前です(これをアプリケーションに適したパッケージ名に置き換えてください)。これは中クラスのためにOKであることをJavaランタイムに指示javafx.graphics
し、javafx.fxml
あなたのクラスの呼び出し反射するorg.jewelsea.demo.javafx.springboot
パッケージ。これが行われ、アプリケーションがコンパイルされて再実行IllegalAccessError
されると、正常に動作し、JavaFXによるリフレクションの使用によって生成されたものは発生しなくなります。
しかし、module-info.javaファイルを作成したくない場合はどうでしょうか。
IDEの上部ツールバーにある[実行]ボタンを使用してアプリケーションクラスを直接実行する代わりに、次のようにします。
- IDEの横にあるMavenウィンドウに移動しました。
- javafxmavenプラグインターゲットを選択しました
javafx.run
。
- それを右クリックして、
Run Maven Build
またはを選択しましたDebug...
。
その後、アプリはmodule-info.java
ファイルなしで実行されます。これは、mavenプラグインが、module-info.java
ファイルがなくてもアプリをJavaFXクラスに反映できるようにする何らかの設定を動的に含めることができるほどスマートであるためだと思いますが、これがどのように行われるかはわかりません。
その設定を上部のツールバーの[実行]ボタンに転送するには、javafx.run
Mavenターゲットを右クリックして、ターゲットのオプションを選択しますCreate Run/Debug Configuration
。次に、上部のツールバーから[実行]を選択するだけで、Mavenターゲットを実行できます。