1. 導入:なぜrequires staticが必要なのか
Java 9で導入されたモジュールシステム(Project Jigsaw)では、アプリケーションの依存関係を厳密に管理できます。しかし、開発中に「特定のライブラリがある場合のみ機能を提供し、ない場合はライブラリなしで動作させたい」というケースが発生します。単なるrequiresを指定すると、そのモジュールがランタイム(実行時)に存在しないだけでアプリケーションが起動しなくなります。この課題を解決し、柔軟な依存関係を実現するのが「requires static」です。
2. 基礎知識:モジュールシステムと依存関係
Javaモジュールシステムにおいて、module-info.javaファイルはモジュールの「設計図」です。
requires:モジュールが動作するために必要な他のモジュールを宣言します。デフォルトでは、コンパイル時と実行時の両方で存在が必須となります。
static:これを付与することで、「コンパイル時には必要だが、実行時には必須ではない(任意)」という依存関係を定義できます。これにより、ライブラリの有無で挙動を変えるような、疎結合な設計が可能になります。
3. 実装と解決策:module-infoの設定
requires staticを使用する場合、コンパイル時にそのモジュールを参照できますが、実行時にはモジュールパスから除外されていてもエラーになりません。ただし、コード内でそのモジュールのクラスを直接参照すると、実行時にNoClassDefFoundErrorが発生する可能性があります。そのため、実行時には必ず「そのクラスが利用可能か」をチェック(Class.forNameやモジュール層の確認)してからアクセスする実装が必須です。
4. サンプルプログラム
以下の例では、外部モジュール「com.example.optional」に依存しつつ、それが存在しない場合でも安全に動作する構成を示します。
// module-info.java
module my.app {
// コンパイル時のみ参照を許可する指定
requires static com.example.optional;
}
// メインの処理クラス
public class App {
public void run() {
// クラスの存在確認(実行時にライブラリがなくても安全)
try {
Class.forName(“com.example.optional.OptionalService”);
useOptionalLibrary();
} catch (ClassNotFoundException e) {
System.out.println(“オプションライブラリが検出されませんでした。標準機能で動作します。”);
}
}
private void useOptionalLibrary() {
// ここで安全にライブラリの機能を利用する
com.example.optional.OptionalService service = new com.example.optional.OptionalService();
service.execute();
}
}
5. 応用・注意点
現場でこの技術を使う際、以下の点に注意してください。
実行環境の確認:requires static を使った場合、実行時にライブラリが読み込まれていない状態でそのクラスを直接newしたりメソッドを呼び出すと、即座に例外が発生します。必ずリフレクションやクラス存在確認を行い、ガード節を設けてください。
ビルドツールの対応:MavenやGradleなどのビルドツールを使用する場合、それらのツール側でもモジュール設定や依存関係のスコープ(compileOnlyなど)を適切に定義する必要があります。
モジュールのオープン化:もしリフレクションで内部のクラスを動的に読み込む場合は、相手側モジュールがopensでパッケージを公開しているか、あるいは自分自身のモジュール設定で適切にexports/opensが管理されているかを確認してください。
適切に使いこなせば、プラグインアーキテクチャのような拡張性の高いアプリケーションをJavaで構築する強力な武器になります。ぜひ試してみてください。

コメント