SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

【最新Javaアップデート解説】変更点と過去バージョンからのおさらい

Java 12~15でアップデートされたJVMの動作に関する変更点は? マイクロサービスの普及による軽量化ニーズが背景に

Java 12からJava 15までの変更点を確認しよう 第2回

  • X ポスト
  • このエントリーをはてなブックマークに追加

アプリケーション・クラス・データ共有機能について

 アプリケーション・クラス・データ共有機能(以下、AppCDS機能)は、Oracle版Javaには以前からあり、Java8での商用版で利用できました。

 そして、OpenJDKではJava10から利用できるようになっています。Java12、Java13では、さらに利用しやすいように改善されています。

アプリケーション・クラス・データ共有機能とは

 Javaプログラムは、実行時にクラスファイルを各プラットフォームで利用できるように変換してから実行されます。AppCDSでは、この工程を事前に行い、ファイルとして保存しておくことで次回の実行時にはその工程をスキップできます。

 そのため、起動時間の短縮が可能になり、また、複数のJVMで共有することもできるため、リソースも節約できます。クラス・データ共有について詳しく知りたい方は、Java仮想マシン・ガイド により詳しく説明されているので、そちらを参照してください。

Java12からのAppCDS機能の利用方法

 通常の流れでは、以下のような3つの手順を経て、準備から実行までをします。

  1. クラス・データ共有として利用するクラス一覧ファイルを準備する
  2. クラス一覧ファイルから、CDSアーカイブファイルを作成する
  3. 作成したCDSアーカイブファイルを指定して、プログラムを実行する

 Java10からと作成方法は同様ですが、これまで必要だったオプションがいらなくなり、多少作成方法が変わっています。まず、クラス・データ共有として利用するクラス一覧ファイルは、リスト5のように実行して作成します。

[リスト5]CDSアーカイブファイルに含めるクラス一覧ファイルの作成
java -Xshare:off -XX:DumpLoadedClassList=class_list.txt  \  //(1)アーカイブするクラスファイル一覧を作成
    //(2)以下、通常のプログラムを実行する際に指定するパラメータを指定
	-cp build/libs/main.jar:build/export/* \
	-Dloader.main=jp.enbind.sample.MainApplication jp.enbind.sample.MainLauncher

 (1)のように「-Xshare:off」を指定し、クラス・データ共有を無効にします。そして「-XX:DumpLoadedClassList」では、出力するアーカイブするクラス一覧ファイルを指定します。これ以降のオプションについては、(2)のように通常、プログラムを実行する際と同じ指定をします。また、このコマンドを実行して作成されたファイルがリスト6です。

[リスト6]作成されたクラス一覧ファイルの例
java/lang/Object
java/lang/String
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/constant/Constable
// ・・・省略
jp/enbind/sample/MainLauncher
org/springframework/boot/loader/PropertiesLauncher
org/springframework/boot/loader/Launcher
//  ・・・省略

 このファイルを見ると、Javaの基本クラスや利用している外部ライブラリや、今回作成したクラスなどが含まれていることがわかります。このファイルを編集して、任意のクラスを追加することや除外することも可能です。

 ただし、想定するクラスが含まれていない場合には、実行される形式に問題がある場合があります。例えば、今回用意したサンプルプログラムはSpringBootを用いたものですが、Jarファイル内に依存するJarファイルが含まれるような特別な形式になっています。

 そのような形式では、CDS機能を生かすことができません。そこで、今回のサンプルでは、通常のJarファイル形式にしています。続いて、リスト7は作成したクラス一覧ファイルを使って、CDSアーカイブファイルを作成する場合の実行例です。

[リスト7]CDSアーカイブファイルを作成する例
java -Xshare:dump -XX:SharedClassListFile=class_list.txt -XX:SharedArchiveFile=cds_archive.jsa  \  //(1)必要なオプションの指定
     // 以下、通常のプログラムを実行する際に指定するパラメータを指定
     -cp build/libs/main.jar:build/export/* \
     -Dloader.main=jp.enbind.sample.MainApplication jp.enbind.sample.MainLauncher

 (1)のように「-Xshare:dump」は、作成されるCDSアーカイブに関する診断情報を出力します。そして、「-XX:SharedClassListFil」には先ほど作成したクラス一覧ファイルを指定し、「-XX:SharedArchiveFile」に出力するCDSアーカイブファイル名を指定します。

 このコマンドを実行するとログが出力され、実際に作成されたクラス状況がリスト8のように結果が表示されます。ここでは、合計で5142個クラス定義がCDSアーカイブファイルに含まれたことがわかります。

[リスト8]実行時の診断情報ログ
// ・・・省略
Number of classes 5142
    instance classes   =  5068
    obj array classes  =    66
    type array classes =     8
Updating ConstMethods ... done.
Removing unshareable information ... done.
//  ・・・省略

 そして、CDSアーカイブファイルを使って実行する場合には、リスト9のようなオプションを指定して実行します。

[リスト9]CDSアーカイブファイルを使った場合の実行例
java  -Xshare:on -XX:SharedArchiveFile=cds_archive.jsa \ //(1) 必要なオプションの指定
	-cp build/libs/main.jar:build/export/* \
	-Dloader.main=jp.enbind.sample.MainApplication jp.enbind.sample.MainLauncher

 (1)のように、「-Xshare:on」は、CDSアーカイブを利用するための指定です。デフォルトで、CDSアーカイブが利用できる場合にはonになるので、この指定は省略しても構いません。「-XX:SharedArchiveFile」には作成されたCDSアーカイブファイルを指定します。

アプリケーション終了時でのCDSアーカイブファイルの自動生成

 ここまでの流れから、共有アーカイブファイルを作成するのは面倒という印象を持つ方もいることでしょう。そこでJava13からは、もう少し簡単に共有アーカイブファイルが作成できるようになりました。具体的には、クラス一覧ファイルを作成することなく、共有アーカイブファイルが作成できるようになっています。そのための実行例がリスト10です。

[リスト10]CDSアーカイブファイルを使った場合の実行例
java -XX:ArchiveClassesAtExit=cds_archive.jsa \ //(1)必要なオプションの指定
	-cp build/libs/main.jar:build/export/* \
	-Dloader.main=jp.enbind.sample.MainApplication jp.enbind.sample.MainLauncher

 (1)のように「-XX:ArchiveClassesAtExit」オプションで作成するCDSアーカイブファイルを指定して実行します。そして、プログラム終了時に共有アーカイブファイルが作成されます。また、CDSアーカイブファイルを利用して実行する際には、先ほどと変わりありません。

実行時間について

 実際に、クラスデータ共有機能を利用しない場合と何も指定しない場合、そして、それぞれの方法でアプリケーション・クラス・データ共有を利用した場合の実行時間をMacOS上で計測した結果が図1です。

図1:AppCDSを使った場合の起動時間の違いについて
図1:AppCDSを使った場合の起動時間の違いについて

 (1)は、起動時に「-Xshare:off」を指定し、意図的にCDS機能を利用しない場合の起動時間です。そして(2)は、AppCDS機能は利用せず、デフォルトのCDS機能のみを使った場合です。(3)は、Java12でのクラス一覧ファイルを使って作ったCDSアーカイブファイルを使い、(4)はJava13での「-XX:ArchiveClassesAtExit」で作成されたCDSアーカイブファイルを使って実行した時の起動時間です。

 今回は、(3)と(4)で時間は変わりませんでしたが、必ずしも同じ結果とならないので、パフォーマンスがうまく出る方法を選択してください。ただし、実際の時間は実行するハードスペックやOSごとに特性は変わります。

 また、実際の時間計測として利用したプログラムはリスト11のようにmain処理までにかかった時間(ミリ秒)です。ここでのサンプルアプリケーションは、SpringBootとJavaFXを用いたアプリケーションであり、実際にはここからさらにさまざまなクラスがロードされ、アプリケーションの開始まで時間がかかります。AppCDSを利用すれば、Javaでの起動部分も短くなるので、さらに効果が見込めるはずです。

[リスト11]AppCDSを使った場合の実行までの時間を計測するためのプログラム(jpackage/src/main/java/jp/enbind/sample/MainLauncher.javaからの抜粋)
public static void main(String[] args) throws Exception {
    long time = ManagementFactory.getRuntimeMXBean().getUptime();
    // ・・・・省略
}

 アプリケーション・クラス・データ共有を使った、アプリケーション全体の起動時間の短縮でも、数100ミリ秒から多くても1、2秒程度しか違いありません。そのため、Javaを常駐型のサービス実行されるような利用ケースではあまりメリットは享受できないと思います。しかし、今後サーバレスのようなオンデマンド型のマイクロサービスへの需要が高まれば、こういった最適化への改善や知見がより重要になってくるに違いありません。

Packaging Tool - Javaアプリケーションのインストーラを作成

 JavaアプリケーションのJVMを含んだ形のインストーラを作成することができるツールが用意されました。このようなツールを利用することで、アプリケーション利用者がJava環境を意識することなく、通常のアプリケーションと同様に配布が行えます。例えば、MacOS用に作成したアプリケーションは、図2のようなOSに準じたインストーラが利用できます。

図2:jpackageを使ったインストーラを実行した際のキャプチャ画像
図2:jpackageを使ったインストーラを実行した際のキャプチャ画像
[リスト12]MacOSでPKG形式のインストーラを作成する場合のコマンド例
jpackage --type pkg --name myJavaApp --input build/libs --main-jar main-app-1.0.jar --icon assets/myJavaApp.icns

 リスト12で使用したオプションは表2で記すオプションを利用しています。その他にも多くのオプションがあるので、詳細はこちらを参照してください。

 ただし、Windows用のパッケージを作成する場合には、別途、WIX TOOLSETが必要になります。また、サンプルコードでは、SpringBootとJavaFXを使ったアプリケーションをGradle(jpackage/build.gradle)でパッケージの作成まで行ったものがあるので、そちらも参考にしてください。

表2:利用する主要なオプション一覧
引数 説明
type 作成するパッケージ形式。Windowsの場合にはmsiもしくはexe形式。MacOSの場合にはdmgもしくはpkg形式。
name アプリケーション名。
input jarファイルを格納しているディレクトリ。
main-jar メインとなるjarファイル。
icon アプリケーションのアイコン(Windowsであればicoファイル、MacOSであればicnsファイル)。

 またjlinkなども合わせて利用することで、配布する容量などの圧縮なども行えるので、より配布しやすいパッケージが作成できるはずです。ただし、まだIncubatorというステータスのために、今後正規リリースされる際には利用できるコマンドなども変わるかもしれませんのでご注意ください。

Remove the Nashorn JavaScript Engine - Java Scriptエンジンの削除

 Java8で導入されたOracle Nashornですが、Java11(JEP335)でDeprecatedになりました。そして、Java15では削除されています。従って、Java15以降でJavaScriptエンジンを使う場合にはGraalVMなどを使う必要があります。

まとめ

 Java12〜Java15での変更点は、Java9やJava11の時に比べると小さい変更と言えます。しかし、Java開発者にとっては、言語仕様にかかわる部分も多いため、知っておくべき変更と言えます。

 そして、実行環境としてのJavaという意味ではよりネイティブプログラムに近い制約でも動くように意識されていると思われます。また、さらに起動時間などを小さくするためには、GraalVMというJava以外でも利用できるVMがあり、そちらを利用することでJavaをネイティブバイナリに変換することも可能です。

 このように、今後Javaは開発言語としての機能だけではなく、実行環境としての変化はより大きくなってくると思われます。その際には、Javaだけのリリース内容だけではなく、GraalVMやOpenJ9などJavaVM側の選択肢も検討することがより重要になります。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
【最新Javaアップデート解説】変更点と過去バージョンからのおさらい連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/12980 2020/10/12 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング