jdepsでの依存取得はロケールまで考えてない
これはjdepsを使ってアプリの依存モジュールを調べ、それによりカスタムJREを構成してその上でアプリを動作させる場合の話である。
問題
メモ:jdeps/jlinkによる縮小JREでは不足が出るという書き込みを見たので、これについて調べてみた。
ごく簡単に書くと、以下のようなプログラムのjarを作る。
import java.nio.charset.*;
public class HelloWorld2{
public static void main(String[]args_) throws Exception {
Charset.forName("EUC-JP");
}
このjarをjdepsで調べてみると依存がjava.baseだけなので、java.baseのみのJREを作成し、その上で動作させてみると、以下のエラーになるという。
java.nio.charset.UnsupportedCharsetException: EUC-JP
at java.base/java.nio.charset.Charset.forName(Charset.java:529)
理由
「Java 9 Modularity: Patterns and Practices for Developing Maintainable」という本に解説されていた。
日時や通貨などのロケール情報についてだが、英語ロケールはjava.baseの一部であり、いつも利用可能だが、他すべてのロケール情報はjdk.localedataにある。これは分離したモジュールなので、ランタイムイメージに加えるかどうか選択が必要だ。ロケール機能はjava.baseからjdk.localedataにexposeされているので、英語以外のロケールが必要であればリンク時に
--add-module jdk.localedata
を使う必要がある。
サービス・プロバイダモジュルールは自動的に解決されないことに注意。
使うには、
--bind-services
が必要だ。
同様の状況はデフォルト(US-ASCII, ISO-8859-1, UTF-8, UTF-16)以外のキャラクタセットを使う時にも発生する。伝統的には、これらはcharsets.jarで提供されてきた。モジュラーJDKでは、jdk.charsetsモジュールを追加すること。
しかし、jdk.localeは極めて大きい。これは15Mバイト程度ある。多くの場合、すべてのロケールは不要だろう。その場合にはjlinkの
--include-locales
フラグを使う。引数として言語タグを使用する(java.util.LocaleのJavaDocを参照すること)。そうすればjlinkプラグインがその他すべてのロケールをjdk.localeが削除する。