Eclipse:モジュールパスとクラスパス



Java9以上でのEclipseの動作

少なくとも最新のEclipseでデフォルトの開発対象をJava9以上にすると、Java8までと比較して以下の違いが現れる。

Javaプロジェクト作成時にmodule-info.javaを作るかと問われる

以下のダイアログだ。モジュールシステムがわかってる人は作ればいいし、そうでない人は作らなくていい。また、ここで作らなくとも、後でプロジェクト右クリックconfigure>create module-info.javaで作成することができる。

ビルドパスのライブラリがモジュールパスとクラスパスに分離している

以下になっている。

JREライブラリが最初からモジュールパスに格納されいる。これはドラッグドロップでクラスパスに移動させることもできるのだが意味がない。なぜなら、実行時の環境でのJREでは、ライブラリは必ずモジュールパスに入っているからだ。

ちなみにJava9以前を開発対象とした場合は、こんな表示になる。

モジュールを使わない場合

Java9以上を開発対象とする場合で、モジュールを理解していない場合(私も良くわかってないのだが)、使う気の無い場合には、以下の方針をとる。つまり、これまで通りということ。

  • アプリにmodule-info.javaを作成してはいけない。
  • ライブラリjarはクラスパスに追加すること。

※原理的には、ライブラリjarはモジュールパスでも良いはずなのだが、実際にはうまくいかない(私が誤解しているのかも)。

モジュールを使う場合

モジュールシステムを使う場合には以下を行う。

開発中アプリにmodule-info.javaを入れる

入れた場合には、(少なくとも開発中の実行では)ルートモジュールを指定したことになり、ルートモジュールのmodule-info.javaを起点にしてのモジュールの依存解決が行われることになる。

もちろん、この場合の「依存解決」が実際に問題になるのは実行時だ。Eclipse上の開発では必要なモジュールは足りていないといけない。そうでないと、Eclipse上でのエラーが発生するからだ。

ライブラリjarファイルはすべてモジュールパスに入れる

クラスパスに入れた場合、それらすべてのjarファイルがまとまって一つの無名モジュールとみなされてしまう。モジュールシステムの使用上、モジュールから無名モジュールは呼び出せないため、エラーになる。

これは、そもそもモジュールシステムがクラスパスに起因する厄介さを解消しようとする目的であるためとのこと。「モジュールシステム」から「クラスパスシステム」を参照することはできないようになっているという。なぜなら、これを許すと結局は「クラスパスの混乱」をモジュールシステムに持ち込むことになってしまうからだそうだ。

方針のまとめ

結局のところ、EclipseでJava9以上を対象とする開発を行う場合には、次のいずれかの方策をとるしかないと思われる。

  • アプリにmodule-info.javaを定義しない。すべてのライブラリjarはクラスパスに入れる。
  • アプリにmodule-info.javaを定義する。すべてのライブラリjarはモジュールパスに入れる。

モジュール開発しても、必ずしも実行時に適用されるわけではない

以上はEclipse上での開発中における話であって、これがそのまま実行時に適用されるわけではない。例えば、

  • いわゆるfat-jarの実行形式を作成した場合にはモジュールシステムは無関係になる。

つまり、ライブラリjarをすべてほぐして、アプリの.classと混ぜ合わせて一つのjarファイルを作成した場合だ。この場合にはおそらくmodule-infoがあろうがなかろうが、何の違いも無いと思われる。

  • warファイルにした場合

現状のサーブレットコンテナにはモジュールを扱う仕様が無いということだ。つまり、warの中にmodule-infoを持つjarがあったとしても、それは普通のjarとして扱われるものと思われる。

モジュール開発することの意味と困難性

もちろん、実行時には無視される可能性があっても「モジュール開発」を行う意味はある。

  • 開発対象がどのモジュールに依存しているのか明確にすることができる。
  • ライブラリの開発であれば、さらに「何を公開するのか」を明確にすることができる。

ただし、これには非常な困難がつきまとうかもしれない。世の中にある多くのライブラリjarファイルはモジュールシステムを前提としておらず、ライブラリjar間あるいは開発対象アプリの間でもエラーが発生する可能性があるからだ。これを覚悟しないとモジュール開発はできないだろう。