きっかけ
JavaのAdvent Callenderでjigsawでカスタムランタイム作ってる記事を見て、そういえばまだやってないなって思ってやろうと決心した。
実験
実装
実験の流れ
- サンプルクラス作成&実行
- jarを作る
- 依存モジュールの調査
- 最小構成JRE作成
- 4で作成した環境で実行してみる。
環境
os
$sw_vers ProductName: Mac OS X ProductVersion: 10.14.2 BuildVersion: 18C54
もう、mojaveです。
最初、 もじゃば
と読んでしまった流派の人です。
モハベ
が正しいらしい。
海外では、ややこしい読み方をカッコいいと感じるのだろうか?
日本だと、無理矢理感のあるルビは、もうイタイの部類に入ってきたと思うが、世界は遅れているな。
ダークモードにしたくて、恐る恐る変えた。
java
$ java -version openjdk version "11.0.1" 2018-10-16 OpenJDK Runtime Environment 18.9 (build 11.0.1+13) OpenJDK 64-Bit Server VM 18.9 (build 11.0.1+13, mixed mode)
実験のたたき台クラス
簡単なサンプルクラスを作る
public class HelloSaga { public static void main(String[] args) { System.out.println("Hello Saga!"); } }
もう、佐賀が好きすぎて hello world じゃなくて hello Saga にしないと気が済まない。
worldより偉大なSagaであります。
コンパイル実行
$ javac HelloSaga.java $ java HelloSaga Hello Saga!
当然、動きますよね。
jarを作る
これから、いろいろやるための準備として、jarを作る。
jar --create --file hello.jar --main-class HelloSaga HelloSaga.class
当然、動きます。
$ java -jar hello.jar Hello Saga!
依存関係を調べる
java9で入った、jdeps
コマンドで、依存しているモジュール郡を調べる。
$jdeps --list-deps hello.jar java.base
System.out.println が標準クラスに属しているので、 java.base
のみが出てくる。
--list-deps
は、公式サイトの説明を見ると、モジュールの依存関係の他、JDKの内部API (参照される場合)のパッケージ名もリストします。
とある。
コマンドの説明が見たい場合は、jdeps -h
で参照可能。
ちなみに、何もつけないで実行した場合、下記の表記になる。
$jdeps hello.jar hello.jar -> java.base <unnamed> -> java.io java.base <unnamed> -> java.lang java.base
java.ioだけだと思ったら、Stringも使ってるから、java.langも入るのか。。。
ただ、どっちもjava.base
に入っているから、見たい情報が重複するので、依存モジュールを見たいときは、--list-deps
をつけるのが良さそう。
小さなJREを作る
依存しているモジュールが、java.base
だけということがわかったので、java.base
のみのJREを作る。
JREを作るには、jlink
コマンドを使う。
jlink --compress=2 --module-path "{jdkのパス}/jmods" --add-modules java.base --output jre-min
自分は、なぜかjlinkの環境パスが通ってなかったので、フルパスを打って実行した。
jenvを使っているのだが、それがいろいろやっているんでしょ?的な感じがした。
本題とそれるので、スルー。
目的を見失うからな。
とりあえず、jlinkのコマンド説明。
参考サイトにもオプション説明はあるが、疑問符が浮かぶ箇所もあったので、改めて説明をまとめる。
引数 | 説明 |
---|---|
--compress=2 | 圧縮オプション。2を指定するとzipで圧縮。0はなし、1は、定数の共有 |
--module-path | jlinkツールで参照可能なモジュールを検出するパス。 |
--add-modules | 追加するモジュール郡。複数指定可能。今回は、java.base のみを使うので、ここに指定 |
–output | 出力する場所 |
オプションを詳しく知りたい場合は、 jlinks -h
で調べられる。
上記のJRE生成コマンドを実行した場合、jremin ディレクトリが作られる。
もとのJREのフォルダのサイズを調べたが、自分の環境では286Mあった。
生成したjreminは、26M。
java.baseしか使ってないからだが、かなり減った。
実行
何も入ってない環境にするのが億劫なので、手打ちで試す。
$jremin/bin/java -jar hello.jar Hello Saga!
無事に動いた!
最悪、javaをインストールしてない環境でも、生成したJREとjarがあれば、動かせるってことですね。
これらをIoT端末に載せて動かそうってのが、意図だろう。
もしかすると、末端の部品は、更に省メモリだから、エッジ端末くらいかもしれないが。
ハードのことは、よくわからんとです。
Androidが可能性として高そうな気がする。
考察
jdeps/jlinkといったツールが、かなり使える印象。
ある程度、ソフトウェアが育ってしまうと、モジュール分割したい要望が出てくるので、それを調査するのにも使えそう。
とういうか、モジュール分割をする作業をjavascriptでかなり苦戦してやっていたので、このツールのありがたみは、よく分かる。
初めてカスタムランタイムを作ったが、思ったよりあっさりできた。
もっと苦戦すると思ったんだがな。
環境周りの知識がついてきているおかげかも知れない。