JavaFX と Project Jigsaw

この記事は、JavaFX Advent Calendar 2015 の 12 日目の記事です。

昨日は @y_q1m さんの JavaFX アプリケーションに隠し Control を搭載する でした。

明日は @tomo_taka01 さんです

ごめんなさい。今日も小ネタです。

JavaOne に行ってからというもの、Project Jigsaw が面白くなっていろいろやってます。

ところで、JavaFXJava SE 9 ではあまり新機能が盛り込まれないようなのです。Feature Complete がちょっと伸びたので、もう少し盛り込むようですが...

で、なんで新機能が少ないかというと、Project Jigsaw への対応が大変だったからということらしいのです。JavaFX 9 については、 id:aoe-tk さんの JavaFX9に追加される機能が増えるかもしれません を見ていただくとして、「じゃあ JavaFX のモジュールはどうなったの?」というところをちょっと調べてみました。

Java SE 9 の java コマンドには -listmods というオプションが追加になって、標準のモジュールの一覧を表示することができます。まずは、これを試してみましょう。

C:\>java -listmods 2>&1 | grep javafx -
javafx.base@9.0
javafx.controls@9.0
javafx.deploy@9.0
javafx.fxml@9.0
javafx.graphics@9.0
javafx.media@9.0
javafx.swing@9.0
javafx.web@9.0

8 個のモジュールが JavaFX に関連するようです。

基本となるのが javafx.base で、コントロールは javafx.controls というようになっているのはわかるのですが、javafx.graphics などがよく分かりません。javafx.base が基本というのは分かりますけど、基本というのはどのぐらいの範囲、つまりどういうクラスが含まれているのかなどもよく分かりません。

これを調べるために、簡単なクラスで試してみました。

public class Test extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        stage.show();
    }
    
    public static void main(String... args) {
        launch(args);
    }
}

単にステージを表示するだけのクラスです。これが含まれる JAR ファイルが test.jar だとします。で、この JAR ファイル (or クラス) がどのようなモジュールを使用しているかを調べるには、jdeps コマンドを使用します。

jdeps -s test.jar
test.jar -> java.base
test.jar -> javafx.graphics

オプションの -s はサマリだけを出力させるオプションです。

ステージを表示するだけで、他には何もやっていないのだから javafx.base に依存しているだろうと思ったら、javafx.graphics に依存していました。もちろん、javafx.graphics は javafx.base に依存しているでしょうから、間接的には依存はしているのですが...

-s オプションを外すと、もうちょっと詳しく見ることができます。

jdeps test.jar
test.jar -> java.base
test.jar -> javafx.graphics
   <unnamed> (test.jar)
      -> java.lang
      -> javafx.application
      -> javafx.stage

やはり、Application クラスや Stage クラスは javafx.graphics モジュールに含まれるようです。

ちょっとサンプルを改造してみましょう。

public class Test extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Label label = new Label("Label");
        
        StackPane root = new StackPane(label);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    
    public static void main(String... args) {
        launch(args);
    }
}

こうすると、依存しているモジュールには javafx.control が出てくるはず。

jdeps -s test.jar
test.jar -> java.base
test.jar -> javafx.controls
test.jar -> javafx.graphics

やはり、javafx.controls に依存していました。

しかし、javafx.base や javafx.graphics はよく分からないままです。こういう時は、モジュールを直接調べてみましょう。

一般的にモジュールには JAR ファイルを使用するのですが、標準のモジュールは JAR ファイルではなく、JMOD ファイルになっています。モジュールが JAR ファイルの時は jar コマンドで調べられるのですが、JMOD ファイルの時は jmod コマンドを使用します。どちらもオプションとして -p (--print-module-descriptor) を使用すれば、モジュールの情報を表示してくれます。

さっそくやってみましょう。JMOD ファイルは JDK のディレクトリの jmods ディレクトリにあります。

C:\Program Files\Java\jdk1.9.0\jmods>jmod javafx.base.jmod -p

Name:
  javafx.base@9.0
Requires:
  jdk.jfr
  java.base [ MANDATED ]
  java.desktop
Exports:
  com.sun.javafx to [javafx.controls, javafx.graphics, javafx.swing]
  com.sun.javafx.beans to [javafx.controls, javafx.graphics, javafx.fxml]
  com.sun.javafx.collections to [javafx.controls, javafx.graphics, javafx.swing, javafx.media]
  com.sun.javafx.binding to [javafx.controls, javafx.graphics]
  com.sun.javafx.event to [javafx.controls, javafx.graphics]
  com.sun.javafx.logging to [javafx.graphics]
  com.sun.javafx.property to [javafx.controls]
  com.sun.javafx.runtime to [javafx.graphics]
  javafx.beans
  javafx.beans.binding
  javafx.beans.property
  javafx.beans.property.adapter
  javafx.beans.value
  javafx.collections
  javafx.collections.transformation
  javafx.event
  javafx.util
  javafx.util.converter
Conceals:
  com.sun.javafx.property.adapter
Hashes:
  Algorithm: SHA-256
  java.desktop: AE4yDbzkIjSeteMHRe9ZMpEkjE/u4PMGSL7WCwpEyOw=
  jdk.jfr: 6hhBHpCTp8ZkLutorg8GIFCp+D9MrL++mIsTh6grzyE=
  java.base: Jjip1psj45/C01FcGzXZc83cwqFHAZVVL3wSXJLiMpc=

外に公開しているパッケージは Exports の項に書いてあります。実をいうと、Exports の部分は順番がぐちゃぐちゃだったので、ソートしなおしてあります。

これを見ると、javafx.base は、意外にもグラフィックに関する部分はまったく含んでおらず、プロパティやバインドに関するクラスだけを含んでいるようです。

ただし、Requires の項に、java.desktop が含まれていることに注意が必要です。java.desktop は AWT や Swing が含まれているモジュールです。これに依存しているので、まったくグラフィックに関連がないというわけではないことが分かります。

次に、javafx.graphics です。

C:\Program Files\Java\jdk1.9.0\jmods>jmod javafx.graphics.jmod -p

Name:
  javafx.graphics@9.0
Requires:
  java.base [ MANDATED ]
  java.desktop
  java.xml
  javafx.base [ PUBLIC ]
Exports:
  com.sun.glass.ui to [javafx.web, javafx.media]
  com.sun.glass.utils to [javafx.web, javafx.media]
  com.sun.javafx.application to [javafx.web, javafx.controls, javafx.deploy, javafx.swing]
  com.sun.javafx.cursor to [javafx.deploy, javafx.swing]
  com.sun.javafx.css to [javafx.controls, javafx.deploy]
  com.sun.javafx.css.converters to [javafx.deploy]
  com.sun.javafx.css.parser to [javafx.deploy]
  com.sun.javafx.embed to [javafx.deploy, javafx.swing]
  com.sun.javafx.font to [javafx.web]
  com.sun.javafx.geom to [javafx.web, javafx.controls, javafx.swing, javafx.media]
  com.sun.javafx.geom.transform to [javafx.web, javafx.controls, javafx.swing, javafx.media]
  com.sun.javafx.iio to [javafx.web]
  com.sun.javafx.jmx to [javafx.web, javafx.swing, javafx.media]
  com.sun.javafx.menu to [javafx.controls, javafx.deploy]
  com.sun.javafx.perf to [javafx.deploy]
  com.sun.javafx.scene to [javafx.web, javafx.controls, javafx.deploy, javafx.swing, javafx.media]
  com.sun.javafx.scene.input to [javafx.web, javafx.controls, javafx.swing]
  com.sun.javafx.scene.text to [javafx.web, javafx.controls]
  com.sun.javafx.scene.traversal to [javafx.web, javafx.controls]
  com.sun.javafx.sg.prism to [javafx.web, javafx.swing, javafx.media]
  com.sun.javafx.stage to [javafx.controls, javafx.deploy, javafx.swing]
  com.sun.javafx.text to [javafx.web, javafx.deploy]
  com.sun.javafx.tk to [javafx.web, javafx.controls, javafx.deploy, javafx.swing, javafx.media]
  com.sun.javafx.util to [javafx.web, javafx.controls, javafx.fxml]
  com.sun.prism to [javafx.web, javafx.media]
  com.sun.prism.image to [javafx.web]
  com.sun.prism.paint to [javafx.web]
  com.sun.scenario.effect to [javafx.web]
  com.sun.scenario.effect.impl to [javafx.web]
  com.sun.scenario.effect.impl.prism to [javafx.web]
  javafx.animation
  javafx.application
  javafx.concurrent
  javafx.css
  javafx.css.converter
  javafx.geometry
  javafx.print
  javafx.scene
  javafx.scene.canvas
  javafx.scene.effect
  javafx.scene.image
  javafx.scene.input
  javafx.scene.layout
  javafx.scene.paint
  javafx.scene.shape
  javafx.scene.text
  javafx.scene.transform
  javafx.stage
Conceals:
   <<省略>>
Hashes:
  Algorithm: SHA-256
  javafx.base: vKYsvlQtkuWc5pwKzHKlUfIp9lXa4SAjnU1TniODA74=
  java.xml: 1FV2E7DCyzOAroiUpxIyJMSg+AzeDI5qm1SmeFyqv4U=
  java.desktop: AE4yDbzkIjSeteMHRe9ZMpEkjE/u4PMGSL7WCwpEyOw=
  java.base: Jjip1psj45/C01FcGzXZc83cwqFHAZVVL3wSXJLiMpc=

こちらも、ソートしなおしてあります。

Applicationや、Scene、Stage も javafx.graphics に含まれていることが分かります。また、イベント関連、CSS 関連なども含まれています。

ちょっと意外だったのが、Animation や Shape も含まれていることです。こういうクラスたちは、外だしされるかと思ってましたけど、基本のところに含まれるんですね。

私がいつも使っているクラスたちは、ほぼ javafx.graphics で済んでしまうということも分かりました。あんまり、コントロール使わないんですよね ^ ^;;; もちろん、仕事では使ってますけど。

ということで、今日はここまで。