Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Java 9のモジュール機能「サービス(SPI)」と既存ライブラリの共存

Java 9で「変わること」と、Javaのこれまで 第3回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2018/01/05 14:00

 前回は、Java 9のモジュール機能「Project Jigsaw」の基本的な使い方を紹介しました。今回はJava 9以前に作られた既存のライブラリとモジュール機能を併せて使う場合の利用方法と、「ServiceLoader」を使う際の変更点を紹介します。

目次

対象読者

  • Java関連に携わる開発者
  • これからJavaを学ぼうと思っている方

既存のライブラリ資産を利用する場合

 Javaにはこれまで蓄積されたライブラリも多く、特にオープンソースライブラリを使わない選択をするのは、多くのプロジェクトで難しいと言わざるを得ません。そしてJava 9へのバージョンアップ後も、それらのライブラリをそのまま使う必要があるケースが多々あります。

 しかし、Java 9がモジュールに対応したことに合わせて、既存の全ての資産をモジュール対応させてリリースし直すのは、現時点では難しいことでしょう。

 Java 9のモジュール機能とモジュール対応されていないライブラリを同時に利用することは可能です。しかし、そのためにはいくつかの注意点があり、Java 9がモジュールをどのように扱っているのか、理解する必要があります。

Java 9におけるモジュールの扱い

 Java 9のモジュールは、以下の3種類に分類できます。

[1]Named Module(Platform Module/Application Module)

 Java 9のモジュール機能形式に沿ったモジュールです。このモジュールにはJDKで提供されているPlatform Moduleとそれ以外のApplication Moduleが存在しますが、基本的な制限事項は同じです。

 ただし、Platform Moduleのjava.baseは全てのコードに依存してしまうため、このモジュールのみ例外としてどのモジュールからも自由にアクセス可能です。また、Application Moduleはモジュールパス(実行時に--module-pathで指定されたパス)に配置する必要があります。

[2]Automatic Module

 この形式は、Java 9以前の形式(module-info.classファイルがない)でパッケージングされたjarファイルがモジュールパスに配置された際、自動的にモジュール扱いになるものです。

 モジュール名は「ファイル名から自動的に命名」されるか、「manifestファイル内のAutomatic-Module-Name属性で指定」します。

ファイル名から自動的に命名される場合

 ファイル名から命名される場合には、ルールに従います。具体的には以下の通りです。

  1. 最後の.jarの拡張子を削除します。
  2. ファイル名にハイフンが含まれて、そのハイフン以降が数値もしくはドットの場合(正規表現で「-(\d+(\.|$))」に一致する場合)、最初のハイフン以前の部分を利用します。
  3. 英数字でない文字(ハイフンなどの記号)は、全てドットに置き換えます。

 つまり、「sample-foo.jar」という名前のjarファイルは「sample.foo」というモジュール名になり、「sample-foo-2.0.1.jar」というファイル名の場合も「sample.foo」というモジュール名になるということです。

manifestファイル内のAutomatic-Module-Name属性で指定する場合

 manifestファイル内でモジュール名をsample.fooと指定する場合には、リスト1の通りにします。

リスト1 manifestファイル(META-INF/MANIFEST.MF)でのモジュール名の指定
Automatic-Module-Name: sample.foo

 どちらの方法で命名されたとしても、このjarファイル内で定義されたパッケージは自動的に全てexportsされたものとして扱われます。これは、その他のモジュールに依存していることも多く、そこで定義が必要になってしまわないためにも必要な扱いといえます。

[3]Unnamed Module

 このモジュールはクラスパスに指定された場合のモジュールです。また、Unnamedとあるようにモジュール名はありません。通常ここに配置されるのはAutomatic Moduleが依存しているライブラリです。

 Application Moduleがコンパイルされる際に、Automatic ModuleとUnnamed Moduleにどのような制限があるかを示したのが図1です。

図1 コンパイル時のモジュールの参照制限
図1 コンパイル時のモジュールの参照制限

 この通り、Unnamed Moduleは参照できません。つまり、コンパイル時にパッケージやクラスが見つからないことになります。したがって、コード内で既存のjarファイル内のクラスにアクセスする場合には、そのjarファイルをモジュールパス内に移動し、Automatic Moduleとして扱う必要があります。

 ただし実行時はコンパイル時と異なり、リフレクションを使ったクラスへのアクセスが可能なため、コンパイル時に問題が生じなくても、実行時にはエラーが発生するケースがあります。

 また、Java 9に以前に作られたライブラリは、Platform Moduleのjava.base以外も全て、何も制限なく参照可能でした。つまり、Java 9以前に作られたライブラリの場合は、ライブラリの中身を何も変更せずにそのまま利用したい事が多いと思います。そのためには、Javaの実行時にコマンドオプションに以下の指定し、モジュールへの参照権限の指定が必要になります。

--add-modules module(,module, ...)

 実行時にモジュールの追加が可能です。

--add-exports module/package=target-module(,target-module, ...)

 実行時に、<module>/<package>を<target-module>からアクセス(exports)できるようにします。

--add-opens module/package=target-module(,target-module, ...)

 実行時に、<module>/<package>を<target-module>からアクセス(opens)できるようにします。

 これらの関係を示したのが図2です。

図2 実行時のモジュールの参照制限とコマンドラインオプションによる指定追加
図2 実行時のモジュールの参照制限とコマンドラインオプションによる指定追加

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしど...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:Java 9で「変わること」と、Javaのこれまで
All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5