Javaのアーティファクトがより良いものに: jpackageはJava 16からプロダクションレディです
JDK(Java Development Kit)14では自己完結型Javaアプリケーションをパッケージングするものとして、Javaツールキットにインキュベーション機能が追加されました。新しくリリースされたJava 16ではこの機能が製品化されています。
異なるプラットフォーム用のコンパイルについて考えると震えるという方、私にはその気持ちがよくわかります。Javaの約束の1つであるWORA(Write Once, Run Anywhere)原則はプラットフォームの独立性に革命をもたらしたものの、もう1つのステップである「どこにでもデプロイできる」ことには至りませんでした。個人的にWORADAは素晴らしいと思いますが、Dockerの登場以前「自分のマシンでは動くのに」問題をなくすのは自分のマシンを出荷するのと同じくらい面倒なことだと思われていたのではないでしょうか。
つまりあなたはクラスを書き、jarファイルを作り、正しいJVM(またはJDK)とすべての依存関係を必要とし、動かすために特殊な作業を行ってきました。この知識が開発サイロから運用サイロに一貫してそのまま送り届けられることは可能なのでしょうか?
「自分のマシンを出荷する」コンテナ革命
コンテナですべてが変わりました。過去数年間「Javaアプリケーションのデプロイに非常に苦労している」という苦情に対して、「少なくともJavaだとすべてのプラットフォームで動作するけど、他はそれさえもできない」と答えていましたが、Dockerとコンテナの台頭により「少なくともマルチプラットフォームである」という議論は水の泡となってしまいました。マルチプラットフォームのサポートは(ターゲットプラットフォームを出荷するので)突然それほど重要ではなくなりましたが、アプリケーション全体を含むパッケージを持つことが勝者となったのです。
ネイティブなJavaアプリケーションのインストーラー・ジェネレーター、jpackage
Docker JEP 311(Java Packager API & CLI)の最初のリリースからわずか4年、ついに日の目を見ました。そのアイデアは古くて放置されていたjavapackagerツール(その目的は「Antタスクの代替として使用されること」でした–Oracleの公式ドキュメントからの引用です、冗談ではありません!)をクリーンアップし、文書化し、適切なAPIを提供し、Java開発者が適切なインストーラを作成できるようにすることでした。そして、JEPの343と392: Packaging Toolに置き換えられました。パッケージングツールはJava 16のリリースできれいに書き直され、素晴らしいものになりました。ご覧ください。
$ jpackage create-installer --runtime-installer \
--name --output outputdir
これですべて(アプリ、依存ファイル、JRE、Kitchen sink)を含むインストーラー(.msi/.exe1、.dmg、.deb/.rpm)を作成したことになります。
すべて?それは言い過ぎでは?
本当にそうなのです。しかし、実際にはすべてをパッケージングする必要はありません。以下のようなコマンドで自分のアプリケーションだけの実行ファイルを作成します。
$ jpackage --name myapp --input lib --main-jar main.jar \
--main-class myapp.Main
このパッケージにはmyapp
と呼ばれるアプリケーションのランチャーが含まれています。アプリケーションを起動するために、ランチャーは入力ディレクトリからコピーされたすべてのJARファイルをJVMのクラスパスに配置します。
JREはどこへ行った?
でも…JREを除外したことで、目的を達成できなかったのでは?はい、そうなのです。JREを含むけれどもすべてではない、という間を取ったやり方を見つけましょう。jlink
コマンドを使って、本当に必要なモジュールだけを含むJREのサブセットを作ることができます。
$ jlink --add-modules java.base,java.sql --output smalljre
これで、smalljre
というカスタムの(そして小さな)JREができました。それを使ってインストーラーを作ってみましょう。
$ jpackage --name myapp --input lib --main-jar main.jar \
--runtime-image smalljre
jpackage
ってかっこいいですよね?その通りです。ではDockerの代わりになるのでしょうか?いえ、そうではありません。それなら何になるのでしょう?お答えしましょう、私たちはスタンドアロンのJavaアプリケーションを持ち、どこでも実行することができる(Run Anywhere)のです。
Javaパッケージをどこへでも
さて、素晴らしいパッケージができました。次はどうしましょう?それは、このパッケージが何であるかによります。ここでは、いくつかのオプションを紹介します。
- ダウンロード可能なデスクトップアプリケーションの場合。クラウドでの配布サービスが必要です。JFrog Platformはまさにそれを実現する無料のクラウドアカウントを提供しています。Javaパッケージをジェネリックリポジトリにデプロイすることで、それを必要な人が自分のデバイスにダウンロード出来るようになります。
- JFrog PlatformはDebianおよびrpmパッケージのリポジトリタイプにも対応しているので、DebianやrpmのJavaパッケージをネイティブにホストし、提供することができます。
- 配布の体験をさらに向上させたい場合、上位のJFrog Platformのサブスクリプションレベルにおいて、世界中どこでもより快適なダウンロード速度を提供するCDN(Content Delivery Network)のサポートが含まれています。
- Dockerイメージの一部である場合。セルフホスティングのために無料のJFrog Container Registryを手に入れるか、JFrog Platformで無料のクラウドアカウントを開設してください。どちらの場合も、あなたのDockerイメージのための無料のDockerレジストリと、それらイメージのコンテンツ、つまり私たちのJavaパッケージのためのジェネリックリポジトリが使えるようになります。次に、シンプルなADD命令で、1つのファイル(Javaパッケージ)をイメージにコピーし、Dockerfileをシンプルに整頓できます。
Java 16 – アプリケーションの簡略化
すべてのjarを集め、任意のJREを追加し、簡単なコマンドですべてをパッケージングすると、Java初心者の「この混乱から一体どうやってアプリケーションを作ればいいのか」という疑問が現実のものとなります。これはjpackageのおかげです。JFrog Platformを使ってどんなターゲットやエンドユーザーにもアクセスできるようにすれば、最強の組み合わせになります。
Java 16のリリースとJavaコミュニティに与える影響については、以下のブログ記事をご覧ください。
Java 16 Commits to Git and GitHub: A Personal Reflection
Java®はOracleおよびその関連会社の商標です。