プロジェクト

全般

プロフィール

JavaFXライブラリのインストール

はじめに

Java SE 11以降、JavaFXはライブラリとして別途インストールするようになりました。本ページは、Java SE 11以降でJavaFXライブラリを利用した開発をするためのインストール作業を記述します。

JavaFXは、OSネイティブなライブラリを含むため、OS別にリリースされたライブラリを入手しインストールします。

入手

JavaFXは、現在次のリリースがあります。

  1. OpenJFXのダウンロードサイト
  2. Gluon社のダウンロードサイト
  3. mavenリポジトリ

OpenJFXのダウンロードサイトから入手

http://jdk.java.net/openjfx/

Gluon社のダウンロードサイトから入手

https://gluonhq.com/products/javafx/
各OS毎(Windows、Mac、Linux)に、SDKとjmodsと2つのアーカイブが提供されます。
SDKには、OSネイティブのライブラリ、JARファイルが含まれています。
jmodsには、Javaモジュールファイル(jmod)が含まれています。jmodファイルはコンパイル・リンク用に使うためのもので、OSネイティブのライブラリが入っています。

開発・実行環境に合わせて必要な方を入手します。

Windows版の入手とインストール

JavaFXライブラリを、C:\Program Fils\Java\JavaFXの下に置くこととします。

Gluon社のダウンロードサイトから次をダウンロードします。
次は、JavaFX 11アーリーアクセス25版の場合です。

名称 ファイル名
JavaFX Windows SDK openjfx-11-ea+25_windows-x64_bin-sdk.zip
JavaFX Windows jmods openjfx-11-ea+25_windows-x64_bin-jmods.zip

各zipファイルを、C:\Program Fils\Java\JavaFXの下に展開します。

C:\Program Files\Java\JavaFX
  +-- javafx-sdk-11
  |     +-- bin
  |     |     +-- *.dll
  |     +-- legal
  |     +-- lib
  |           +-- *.jar
  +-- javafx-jmods-11
        +-- *.jmod

動作確認

ライブラリをインストールしたら、動作確認のため簡単なプログラムをビルド・実行します。

Hello world

作業ディレクトリの作成

作業ディレクトリを用意し、ソースコードを置くディレクトリ、コンパイル結果を置くディレクトリを作ります。

hello
  +-- build
  +-- src
        +-- hellofx                   <-- モジュール名に一致する名前
              +-- com                 <-- パッケージ名に基づくディレクトリ名
                    +-- torutk        <-- パッケージ名に基づくディレクトリ名
                          +-- hello   <-- パッケージ名に基づくディレクトリ名

ソースファイルを作成

  • src\hellofx\com\torutk\hello\Hello.java
    package com.torutk.hello;
    
    import javafx.application.Application;
    import javafx.stage.Stage;
    
    public class Hello extends Application {
        @Override
        public void start(Stage primaryStage) {
        primaryStage.show();
        }
    }
    

モジュール記述子を作成

  • src\hellofx\module-info.java
    module hellofx {
        requires javafx.controls;
    }
    

今回のソースコードから利用するJavaFXのAPIは、javafx.graphicsモジュールに含まれますが、アプリケーションからは通常はjavafx.controlsモジュールへの依存を定義します。javafx.controlsは、javafx.graphicsへの依存(推移的依存)を

ソースファイルの構成

この時点で作業ディレクトリには次の様にファイルが置かれます。

hello
  +-- build
  +-- src
        +-- hellofx
              +-- module-info.java
              +-- com
                    +-- torutk
                          +-- hello
                                +-- Hello.java

コンパイル

D:\work\hello> javac -d build -p "C:\Program Files\Java\JavaFX\javafx-sdk-11\lib" --module-source-path src -m hellofx

D:\work\hello> 
  • -dオプションでコンパイル結果出力先ディレクトリを指定
  • -pオプションでJavaFXライブラリ(JARファイルまたはjmodファイル)が収められた場所を指定
    -pは、--module-pathの省略形
  • --module-source-pathでコンパイルするモジュールのソースファイルが収められた場所を指定
  • -mオプションでコンパイルするモジュールを指定
    -mは、--module-nameの省略形

コンパイル結果は次のようになります。

hello
  +-- build
        +-- hellofx
              +-- module-info.class
              +-- com
                    +-- torutk
                          +-- hello
                                +-- Hello.class

コンパイル結果の実行

D:\work\hello> java -p build;"C:\Program Files\Java\JavaFX\javafx-sdk-11\lib" -m hellofx/com.torutk.hello.Hello

モジュールJARファイルの作成

先のビルド結果から、モジュールJARファイルを生成します。

D:\work\hello> jar cfe build\mods\hellofx.jar com.torutk.hello.Hello -C build\hellofx .
  • cfオプションで新たにJARファイルを指定したパスで生成
  • eオプションでエントリポイントのクラスを指定

モジュールJARファイルの実行

D:\work\hello> java -p build\mods;"C:\Program Files\Java\JavaFX\javafx-sdk-11\lib" -m hellofx

モジュールJARファイルの生成時にエントリポイントを指定したので、-mオプションではモジュール名だけ指定します。

リンク(アプリケーション実行用のイメージ作成)

アプリケーションを実行するのに必要なモジュールだけを抜粋したJava実行環境を作成します。

D:\work\hello> jlink -p "build;%JAVA_HOME%\jmods;C:\Program Files\Java\JavaFX\javafx-jmods-11" --add-modules hellofx --launcher hello=hellofx/com.torutk.hello.Hello --output hellofx-image

実行します。

D:\work\hello> hellofx-image\bin\hello

トラブルシューティング

Application派生クラスで実行時例外(InvocationTargetException)

Exception in Application constructor
Exception in thread "main" 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:566)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class com.torutk.hello.Hello
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:890)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalAccessException: class com.sun.javafx.application.LauncherImpl (in module javafx.graphics) cannot access class com.torutk.hello.Hello (in module hellofx) because module hellofx does not export com.torutk.hello to module javafx.graphics
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:802)
        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(Native Method)
        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)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
        ... 1 more

javafx.graphicsモジュール(Applicationクラスを含むモジュール)が、Application派生クラスへリフレクションを使ったアクセスをする際にエラーとなっています。
モジュール記述子でアプリケーションのモジュールを公開する必要があります。

次の記述を追加します。

  opens com.torutk.hello to javafx.graphics;

jlinkで生成したイメージの実行時例外

jlinkで実行イメージを生成する際に、JavaFXのSDKを指定した場合、つまりモジュールJARファイルのある場所を指定した場合、次のエラーが実行時に発生しました。

D:\work\hello> hellofx-image\bin\hello
Graphics Device initialization failed for :  d3d, sw
Error initializing QuantumRenderer: no suitable pipeline found
java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:222)
        at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:260)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
        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:566)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:94)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
        at java.base/java.lang.Thread.run(Thread.java:834)
Exception in thread "main" 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:566)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: No toolkit found
        at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:272)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        ... 5 more

JARファイルのある場所を指定して実行イメージを生成すると、ネイティブライブラリが展開されません。
解決には、jmodファイルのある場所を指定する必要があります。jmodファイルにはネイティブライブラリが含まれているので、生成された実行イメージにはネイティブライブラリが含まれます。

クリップボードから画像を追加 (サイズの上限: 1 GB)