[Java] Automating The Creation of JDK9 Reduced Runtime Images in NetBeans

原文はこちら。
https://blogs.oracle.com/jtc/entry/automating_the_creation_of_jdk9

JDK9の次期リリースでは、Java SEプラットフォームはモノリシックな構造に変わって、一連のモジュールを組み合わせて構築されます。
JDK 9 Project
https://jdk9.java.net/
この大きな変化に伴い、開発者は自身のアプリケーションをモジュール化することができ、さらに、アプリケーションを実行するために必要なモジュールだけを使ってランタイムイメージを作成することができます。この大規模な進化について多くの記事が出ていますし、これからも出てくることでしょう。今日は、カスタムランタイムイメージを作成する機能と、NetBeansなどの統合開発環境でその作成方法を自動化する方法について説明します。
NetBeans IDE
https://netbeans.org/
最初に、早期アクセス版JDK9と、それに対応する早期アクセスJDK9対応 NetBeansをダウンロードして、始めることにしましょう。
JDK™ 9 Early Access Releases
https://jdk9.java.net/download/
NetBeans IDE Nightly Build ダウンロード
http://bits.netbeans.org/download/trunk/nightly/latest/
このレシピでは、SimpleAppという非常に単純なJDK9アプリケーションを作成し、Java Logging APIを使用してメッセージをログに記録します。
Package java.util.logging
http://download.java.net/java/jdk9/docs/api/java/util/logging/package-summary.html
すべてのJava 9プログラムでは、java.baseというモジュールを使用する必要があります。このプログラムでロギングメソッドを呼び出すためには、java.loggingと呼ばれる追加のモジュールを取り込む必要があります。以下はNetBeansプロジェクトとソースコードの例です。

NetBeansでこのプログラムを実行すると、出力ウィンドウに以下のような表示が現れます。

このプログラムをモジュール化するために、まずモジュールの依存性を識別する必要があります。JDK 9のユーティリティjdepsを使って、以下のようにこの作業を実行することができます。

最初に、jdeps -versionを呼び出し、JDK 9版のjdepsを使っていることを確認します。続いて、NetBeansで作成した SimpleApp.jar に対して jdeps -s を呼び出し、モジュール依存性を取得します。この例では、作成したプログラムには2個のモジュールが必要です。前述の通り、全てのJava 9アプリケーションはデフォルトで java.base というモジュールが必要です。さらに、今回のプログラムではモジュール java.logging のメソッドを呼ぶため、 java.logging にも依存します。
この情報を基に、SimpleAppプロジェクトを右クリックし、New->Java Module Info...を選択してNetBeansプロジェクト内にファイル module-info.java を作成します。

作成した後、module-info.javaはSimpleAppのデフォルトパッケージになります。モジュール仕様は最初は空で、以下のように2個のrequiresと、1個のexportsを追加します。

module-info.java を適切に設定したのち、 SimpleApp をビルドします。NetBeansはコンパイル済みの module-info.class をSimpleApp.jarに追加し、モジュールのJarファイルにします。
ゲームの少し早い段階ですが、JDK9のjlinkユーティリティを使用してランタイムイメージを構築する機能が、現時点でNetBeansには欠けているように見えるので、この機能を提供するようNetBeansをカスタマイズしてみましょう。より洗練されたソリューションは間違いありません。この機能を使えば、実際に実行されるJavaコマンドを出力することで、デバッグを支援することができます。
まず、SimpleAppのNetBeans project.propertiesファイルを探して編集します。 このファイルはNetBeansの[ファイル]タブをクリックすると、プロジェクトのファイルシステムビューが表示されます。 nbproject ディレクトリの下に、project.propertiesファイルがあります。 project.propertiesをダブルクリックすると、そのファイルを編集用に開くことができます。

以下のテキストを projects.properties ファイルの最後に追加します。
#
# Added to support creation of modular jar and jlink image.
# Change this property to match your JDK9 location
#
jdk9.basedir=C:\\Users\\jtconnor\\jdk-9
#
modular.jar.command=${jdk9.basedir}\\bin\\jar.exe
modular.jar.file=${dist.dir}\\${application.title}.jar
#
modular.jar.arg1=--verbose
modular.jar.arg2=--update
modular.jar.arg3=--file
modular.jar.arg4=${modular.jar.file}
modular.jar.arg5=--main-class
modular.jar.arg6=${main.class}
modular.jar.arg7=--module-version
modular.jar.arg8=1.0
modular.jar.arg9=-C
modular.jar.arg10=${build.dir}\\classes
modular.jar.arg11=module-info.class
modular.jar.args.concatenated=${modular.jar.arg1}  ${modular.jar.arg2} ${modular.jar.arg3} ${modular.jar.arg4}  ${modular.jar.arg5} ${modular.jar.arg6} ${modular.jar.arg7}  ${modular.jar.arg8} ${modular.jar.arg9} ${modular.jar.arg10}  ${modular.jar.arg11}
#
jlink.command=${jdk9.basedir}\\bin\\jlink.exe
jlink.module.dependency1=${modular.jar.file}
jlink.module.dependency2=${jdk9.basedir}\\jmods
jlink.module.path=${jlink.module.dependency1};${jlink.module.dependency2}
jlink.image.dir=${dist.dir}\\jimage
#
jlink.arg1=--module-path
jlink.arg2=${jlink.module.path}
jlink.arg3=--add-modules
jlink.arg4=${application.title}
jlink.arg5=--output
jlink.arg6=${jlink.image.dir}
jlink.arg7=--compress=2
jlink.args.concatenated=${jlink.arg1} ${jlink.arg2} ${jlink.arg3} ${jlink.arg4} ${jlink.arg5} ${jlink.arg6} ${jlink.arg7}
まぁ悪くないですね。基本的には、JDK9のjarユーティリティとjlinkユーティリティを実行するためのコマンドライン引数を設定することです。この設定では、モジュールのjarやランタイムイメージ作成に失敗した場合のデバッグがより簡単にできるはずです。1点、重要なポイントとして、jdk9.basedirプロパティを適切に設定する必要があります。
#
# Added to support creation of modular jar and jlink image.
# Change this property to match your JDK9 location
#
jdk9.basedir=C:\\Users\\jtconnor\\jdk-9  <-- ここをご自身のJDK 9の場所に変更してください!
この手順が完了したら、SimpleAppのビルドファイル(build.xml)を変更しましょう。その前に、このファイルはFileタブのSimpleApp/ディレクトリにあります。build.xmlをダブルクリックしてファイルを編集します。

ファイルを開き、最終行に移動します。追加のantタスクを</project>の前に以下のように配置します。

以下は追加するテキストです。
<target name="-post-jar" depends="-do-modular-jar,-do-jlink">
    </target>
    
    <target name="-do-modular-jar">
        <echo message="Updating ${dist.jar} to be a modular jar."/>
        <echo message="Executing: ${modular.jar.command} ${modular.jar.args.concatenated}"/>
        <exec executable="${modular.jar.command}">
            <arg value="${modular.jar.arg1}"/>
            <arg value="${modular.jar.arg2}"/>
            <arg value="${modular.jar.arg3}"/>
            <arg value="${modular.jar.arg4}"/>
            <arg value="${modular.jar.arg5}"/>
            <arg value="${modular.jar.arg6}"/>
            <arg value="${modular.jar.arg7}"/>
            <arg value="${modular.jar.arg8}"/>
            <arg value="${modular.jar.arg9}"/>
            <arg value="${modular.jar.arg10}"/>
            <arg value="${modular.jar.arg11}"/>
        </exec>
    </target>
    
    <target name="-do-jlink">
        <echo message="Creating jlink image in ${jlink.image.dir}/."/>
        <echo message="Executing: ${jlink.command} ${jlink.args.concatenated}"/>
        <exec executable="${jlink.command}">
            <arg value="${jlink.arg1}"/>
            <arg value="${jlink.arg2}"/>
            <arg value="${jlink.arg3}"/>
            <arg value="${jlink.arg4}"/>
            <arg value="${jlink.arg5}"/>
            <arg value="${jlink.arg6}"/>
            <arg value="${jlink.arg7}"/>
        </exec>
    </target>
SimpleApp プロジェクトの変更が完了しました。NetBeansでSimpleAppを "Clean and Build" すると、追加したantタスクが実行されます。以下はNetBeansの出力ウインドウに現れた出力例です。

最後に、ビルドされたものとカスタムランタイムイメージの実行方法を見てみましょう。 以下のスクリーンショットでは、NetBeansによって構築されたSimpleAppのdistディレクトリを調べています。SimpleApp.jar(モジュールjarファイル)とjimage ディレクトリ(カスタムランタイムイメージ)の2つのエントリがあることがわかります。続いて、JDK9ランタイムであることを示すためにjimage ディレクトリでjava -versionを実行し、java -list-modulesを実行して、このランタイムに含まれるモジュールを表示します。ここでは、3個のみ現れますが、本格的なJDK9ランタイムの場合は、通常90個前後現れます。そして最後のコマンドでは、SimpleAppアプリケーションがjimage/ ランタイムからどのように実行されるかを示しています。

上記の例はWindowsプラットフォームの場合です。LinuxやMacで実施したい場合には、project.propertiesファイルを適宜変更する必要があります。このエントリがJava 9の新機能のいくつかの理解に役立つことを願っています。

0 件のコメント:

コメントを投稿