jdepsでの依存取得はロケールまで考えてない

2019年7月3日

これは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が削除する。