JDK7u6に入ってくるJavaFXのネイティブパッケージ機能を早速試してみました

先日、OracleJava開発に関するblogに "Native packaging for JavaFX" なるエントリが載っていたことを知りました (こちらに江草ロジ子さんによる日本語訳もあります) 。


JavaFX 2.2 adds new packaging option for JavaFX applications, allowing you to package your application as a "native bundle". This gives your users a way to install and run your application without any external dependencies on a system JRE or FX SDK.
なんとJavaFX2.2にはOSネイティブなパッケージを生成する機能が付いてくるということです!
具体的にはJavaFXアプリケーションをWindowsなら.exeや.msiMacなら.appや.dmg、そしてLinuxならrpmの形でアプリケーションパッケージやインストーラーを出力できるようになるということです。
パッケージにはJREJavaFXのランタイムも含めてしまい、配布先にJavaFXのランタイムはおろか、JREが入っていなくてもインストール、実行可能にすることができるということです。
これは今までのJavaの歴史を考えると結構衝撃的な話だと思っています。

と言うわけで早速試してみました。

この機能はJDK7u6の最新版のDeveloper Previewに入っているので、まずは以下の場所からダウンロードします。
http://jdk7.java.net/download.html

自分はMac環境で試しました。ダウンロードしたインストーラーを使ってインストールするだけです。
既にJDK7のGA版をインストールしている場合は上書きしてしまうので注意してください。

$ java -version
java version "1.7.0_06-ea"
Java(TM) SE Runtime Environment (build 1.7.0_06-ea-b14)
Java HotSpot(TM) 64-Bit Server VM (build 23.2-b05, mixed mode)

$ /usr/libexec/java_home 
/Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home

自分の環境だと、NetBeansJavaプラットフォーム設定の変更も必要でした。以下のスクリーンショットのように、デフォルトJavaプラットフォームの設定で、JDK7u6のパスを指定する必要があります。

では早速試してみます。NetBeansのビルドでネイティブパッケージを生成したい場合、NetBeansJavaFXアプリケーションプロジェクトの直下にあるbuild.xmlに対して、次のように -post-jfx-deploy タスクをオーバーライドします。fx 名前空間の記述の追加が必要なことに注意してください ( タグの記述を参照) 。

<project name="MouseInfoSample" default="default" basedir="." xmlns:fx="javafx:com.sun.javafx.tools.ant">

(中略)

    <target name="-post-jfx-deploy">
        <fx:deploy width="${javafx.run.width}" height="${javafx.run.height}" nativeBundles="all"
            outdir="${basedir}/${dist.dir}" outfile="${application.title}">
             <fx:info title="${application.title}" vendor="${application.vendor}"/>
             <fx:application name="${application.title}" mainClass="${javafx.main.class}">
             </fx:application>
             <fx:resources>
                 <fx:fileset dir="${basedir}/${dist.dir}" includes="${application.title}.jar"/>
             </fx:resources>
        </fx:deploy>
    </target>
</project>

ポイントは タグの属性に入っている nativeBundles="all" という記述です。これで実行しているOSに応じたネイティブパッケージを生成するようになります。

これでNetBeansの構築を実行したところ、appの生成には成功しましたが、dmgの生成には失敗しちゃいました。

Launching <fx:deploy> task from /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/lib/ant-javafx.jar
Using base JDK at: /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk
Creating app bundle: /Users/aoetakashi/NetBeansProjects/MouseInfoSample/dist/bundles/MouseInfoSample.app
Building DMG package for MouseInfoSample
java.io.IOException: Exec of failed with code 1 command [[osascript, /var/folders/m5/vk8q5qx16yd2scc1jt0mlv100000gn/T/build3045467055592762416.fxbundler/macosx/MouseInfoSample-dmg-setup.scpt] in unspecified directory
	at com.sun.javafx.tools.packager.bundlers.IOUtils.exec(IOUtils.java:130)
	at com.sun.javafx.tools.packager.bundlers.IOUtils.exec(IOUtils.java:108)
	at com.sun.javafx.tools.packager.bundlers.MacDMGBundler.buildDMG(MacDMGBundler.java:262)
	at com.sun.javafx.tools.packager.bundlers.MacDMGBundler.bundle(MacDMGBundler.java:71)
	at com.sun.javafx.tools.packager.PackagerLib.generateNativeBundles(PackagerLib.java:453)
	at com.sun.javafx.tools.packager.PackagerLib.generateDeploymentPackages(PackagerLib.java:434)
...

でも、この例外メッセージが出る前に、何故かそのdmgが以下のスクリーンショットのように「マウント」はされていたんですよね。うーむ不思議だw

いくつかのJavaFXプロジェクトで試しましたが、同じ結果でした。まあ、今回はここについてはまだ深くは調べていません。とりあえずappが出来たので自分的にはOKですw
で、できあがったappはちゃんとダブルクリックで普通に起動します。デフォルトでも結構かっこいいアイコンです。
でも、ファイルサイズを見てみると...

166.9MBだとぉ!?
ちなみにアプリ本体のJARのサイズは20KBです。いったい何が入っているんだと思って中身を見てみると...。

はい、JDK丸ごと入っていました。いくら何でもワイルドすぎやろこれwww

とまあ、こんな感じでした。色々と問題はありますが、まだ実験段階ですし、これから少しずつ洗練されていくでしょう。
アプリケーションの配布形態としてネイティブパッケージという選択肢が出てきたことは素直に嬉しいことだと思っています。
ランタイムごと配布するので、配布先の環境のことを考慮しなくてもいいというのは色んな場面で効いてくるでしょう。例えばなかなかソフトウェア環境を更新してくれない企業向けとか...。*1
もっとも、これはデスクトップアプリ向けというよりはiOSWindows Metroの方をにらんで用意した機能だと見ています。

と言うわけで皆さんも是非試してみてください。
今度はWindowsでも試してみよう。

*1:以前、電子政府で要求JREのバージョンがばらばら、バージョンアップへの追従も遅いという問題が報じられていたことがあったように記憶していますが、そういうのにも向いていそうですね。