拡張機能メカニズムのアーキテクチャー

目次

はじめに

注: オプションパッケージは、これまで標準拡張機能として知られてきたものの新しい名称です。「拡張機能メカニズム」は、オプションパッケージの使用をサポートする、JDK™ および JRE™ の機能です。

このドキュメントでは、オプションパッケージを処理するための Java™ プラットフォームが提供するメカニズムについて説明します。オプションパッケージは、1 つまたは複数の JAR ファイルにまとめられたパッケージの集まりで、Java プラットフォームを拡張する API を実装します。オプションパッケージはプラットフォームを拡張して、仮想マシンが、クラスパスに存在しないクラスをプラットフォームのコア API のクラスとして検索し、ロードできるようにします。

オプションパッケージは、プラットフォームのコア API を拡張するため、適切に適用する必要があります。通常は Java Community ProcessSM で定義されたインタフェースなど、適切に標準化されたインタフェースのために使用されますが、サイト全体のインタフェースに適用されることもあります。オプションパッケージが単一または少数のアプリケーションで使用されるインタフェースに適用されることはほとんどありません。

また、インストール型オプションパッケージで定義される記号はどの JAVA プロセスでも視認できるため、必ずすべての参照可能な記号が所定の「逆順ドメイン名」および「クラス階層」の規約を守っているか気を付けて見るようにします (com.mycompany.MyClass など)。

オプションパッケージの実装は、Java プログラミング言語で記述されたコードですが、まれに、プラットフォーム固有のネイティブコードが含まれる場合もあります。さらに、プロパティー、ローカリゼーションのカタログ、イメージ、直列化されたデータ、およびその他のリソースなど、そのオプションパッケージに固有の各種リソースが含まれることもあります。

Internet Explorer や Netscape Navigator などのブラウザでは、オプションパッケージは Java Plug-in によってサポートされています。

オプションパッケージは、オープンで標準的な API を実装したものです (Sun が提供するオプションパッケージは、JavaServletJava3DJavaManagement など)。例外もありますが、オプションパッケージの多くは javax.* の名前空間に割り当てられます。

拡張機能メカニズム

アーキテクチャー

拡張機能メカニズムは、次の要素を含むように設計されています。 したがって通常、アプリケーションでは、必要なオプションパッケージ (より一般的な言い方をすれば、ライブラリ) を指定して、さらに提供する必要があります。システムは、インストールされているオプションパッケージ (およびライブラリ) がある場合は、それを選び、ない場合は、参照されているオプションパッケージ (およびライブラリ) クラスの検索とロードをアプリケーションのクラスローダーに委譲します。

このアーキテクチャーでは、アプリケーション、アプレット、およびサーブレットがそれら自体のクラスパスを拡張できるので、それらを複数の JAR ファイルとしてまとめ、配置することも可能になります。

それぞれのオプションパッケージまたはアプリケーションは、少なくとも 1 つの JAR ファイルで構成されます。JAR ファイルにはマニフェスト、コード、各種リソースが含まれることもあります。後述するように、このプライマリ JAR ファイルには、ほかの JAR ファイルとの依存関係を記述するため、そのマニフェストに付加情報を含めることもできます。JDKに収録されている jar コマンド行ツールには、オプションパッケージをひとまとめにする便利な機能があります。(jar ツールの参照ページ: [Microsoft Windows] [Solaris™ Operating System (Solaris OS)、Linux])

オプションパッケージまたはアプリケーションは、プライマリ JAR ファイルから参照される別の JAR ファイルを参照することもあります。これらの JAR ファイルには、JAR ファイルごとに独自の依存関係情報を含めることもできます。

オプションパッケージを構成するパッケージは、オプションパッケージの実装時には、標準的なパッケージ命名規約に従って命名する必要があります。この命名規約は「Java 言語仕様」で大筋が示されていますが、ドメインの接頭辞はすべて大文字で指定するという規則はなくなりました。たとえば、COM.sun.server というパッケージ名は com.sun.server とも指定できます。アプリケーションとオプションパッケージは同じクラスローダーを共有する場合があるので、名前の衝突を避けるため、パッケージには一意の名前を付けることをお勧めします。

オプションパッケージの配置

オプションパッケージは、アプリケーションにバンドルする (バンドル型) 方法と、すべてのアプリケーションで使用できるように JRE にインストールする (インストール型) 方法があります。バンドル型オプションパッケージはアプリケーションと同じコードベースに置かれ、ネットワークアプリケーション (アプレット) の場合は自動的にダウンロードされます。したがって、バンドル型オプションパッケージは、ダウンロード型オプションパッケージと呼ばれる場合があります。バンドル型オプションパッケージの JAR ファイルのマニフェストにバージョン情報が含まれ、その JAR ファイルに署名がなされている場合、ダウンロード先の JRE の拡張機能ディレクトリにインストールすることができます (「Java 拡張機能の配備」を参照)。インストール型オプションパッケージは、最初に使用されるときにロードされ、同じ JRE を使用するすべてのアプリケーションによって共有されます。

オプションパッケージをまとめる場合には、JAR ファイルのマニフェストはベンダーおよびバージョン情報を識別するために使用されます (「パッケージのバージョンID」を参照)。

インストール型オプションパッケージのクラスは、同じ仮想マシン上のすべてのコードによって共有されます。したがって、インストール型オプションパッケージはそのプラットフォームの (rt.jar の) コアクラスに似ていますが、インストール型オプションパッケージは、後述するように、専用のクラスローダーと事前に構成されたセキュリティーポリシーを持ちます。

バンドル型オプションパッケージのクラスは、該当アプリケーション、アプレット、またはサーブレットのクラスローダーだけが使用します。アプレットなどのネットワークアプリケーションの場合、バンドル型オプションパッケージは必要に応じて自動的にダウンロードされます。現時点では、クラスローダーは特定のコードベースに関連付けられているので、同じコードベースに置かれたアプレットであれば実装 (JAR) を共有できます。ただし、前述のようにバージョン情報を持ち署名されたバンドル型オプションパッケージが JRE にインストールされている場合、それらの内容は、同じ JRE によって動作するすべてのアプリケーションで使用可能であり、専有されるものではありません

バンドル型オプションパッケージ

アプリケーションまたはオプションパッケージのマニフェストでは、必要なオプションパッケージ (およびその他のライブラリ) が含まれる JAR ファイルとディレクトリを参照する相対 URL を 1 つ以上指定できます。これらの相対 URL は、アプリケーションまたはオプションパッケージが含まれている JAR ファイルのロード元であるコードベースと相対的な位置関係にあるものとして扱われます。

アプリケーション (より一般的には、JAR ファイル) は、必要なオプションパッケージ (およびライブラリ) の URL を、マニフェスト属性 Class-Path で指定します。この属性では、ホストの Java 仮想マシン* にインストールされたオプションパッケージの中から目的のオプションパッケージ (またはその他のライブラリ) の実装が見つからなかった場合に検索する URL を列挙します。この相対 URL には、アプリケーションまたはオプションパッケージが必要とするライブラリまたはリソースが含まれる JAR ファイルとディレクトリを含めることができます。「/」で終わらない URL は、JAR ファイルを参照しているものとみなされます。次に例を示します。

Class-Path: servlet.jar infobus.jar acme/beans.jar images/
JAR ファイルのマニフェストで指定できる Class-Path ヘッダーは 1 つだけです。

現時点では、セキュリティー上の理由により、URL は JAR ファイルのコードベースから相対的に指定する必要があります。したがって、リモートオプションパッケージは、アプリケーションと同じコードベースを元にして指定します。

それぞれの相対 URL は、アプリケーションまたはオプションパッケージが含まれている JAR ファイルのロード元であるコードベースと突き合わせる形で解決されます。解決された URL が無効であるか、参照するリソースが見つからない場合、その URL は無視されます。

解決された URL は、アプリケーション、アプレット、またはサーブレットのクラスパスの拡張に使用され、クラスパスの、そのアプリケーション、アプレット、またはサーブレットが含まれる JAR ファイルの URL の直後に挿入されます。重複する URL は取り除かれます。たとえば、次のようなクラスパスが指定されているとします。

a.jar b.jar
オプションパッケージ b.jar に、次のようなマニフェスト属性 Class-Path が含まれている場合
Class-Path: x.jar a.jar
最終的なアプリケーションクラスパスは次のようになります。
a.jar b.jar x.jar
もちろん、x.jar に依存情報が含まれる場合は、依存ファイルはこれと同じ規則に従って追加されます。あとに続く URL についても同様です。実際の実装では、JAR ファイルの依存関係は先に処理されるのではなく、JAR ファイルが実際に必要になったときまで開かれません。

インストール型オプションパッケージ

Sun による Java 2 プラットフォームの実装以降、インストール型オプションパッケージの JAR ファイルは、次の標準のローカルコードソースに置かれます。
<java-home>\lib\ext                     [Microsoft Windows]
<java-home>/lib/ext                     [Solaris OS, Linux]

ここで <java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JRE のトップレベルディレクトリまたは JDK の jre ディレクトリ) を指します。

システムプロパティー java.ext.dirs を使用すると、インストール型オプションパッケージを置く場所を指定できます。このプロパティーには、インストール型オプション機能を検索するディレクトリを指定できます。複数のディレクトリを指定する場合は、File.pathSeparatorChar で区切ります。java.ext.dirs のデフォルトの設定値は、上に示したインストール型オプション機能の標準のディレクトリになっています。Java 6 以降に改良されたデフォルト設定では、同じシステムにインストールされたすべての JRE (Java 6 以降) によって共有されるプラットフォーム固有のディレクトリへのパスが付けられます。

%SystemRoot%\Sun\Java\lib\ext           [Microsoft Windows]
/usr/java/packages/lib/ext              [Linux]
/usr/jdk/packages/lib/ext               [Solaris OS]

さらに、インストール型オプションパッケージは、1 つ以上の共有ライブラリ (.dll ファイルなど) と実行可能ファイルを含んでいます。そのあと、<arch> が表示されますが、実際には命令セットアーキテクチャーの名前、たとえば sparcsparcv9i386amd64 などが続きます。これらは 2 つの場所のいずれかにインストールされます。最初に検索されるのは次のディレクトリです。

<java-home>\bin                         [Microsoft Windows]
<java-home>/lib/<arch>                  [Solaris OS, Linux]

次に検索される拡張機能ディレクトリは、Java 6 以降にのみ適用されます。Java パッケージと同様、ネイティブライブラリはすべての Java 6 とそれ以降の JRE によって共有されるディレクトリにインストールできます。

%SystemRoot%\Sun\Java\bin               [Microsoft Windows]
/usr/java/packages/lib/<arch>           [Linux]
/usr/jdk/packages/lib/<arch>            [Solaris OS]

ネイティブコードが含まれるオプションパッケージは、信頼できるコードか信頼できないコードかにかかわらず、実行時にネットワークコードにより仮想マシンにダウンロードすることはできません。ネイティブコードが含まれ、ネットワークアプリケーションとともにバンドルされているオプションパッケージは、JDK または JRE にインストールする必要があります。

デフォルトでは、この標準のディレクトリに置かれたインストール型オプションパッケージは信頼できます。つまり、このディレクトリに置かれたインストール型拡張機能には、コアプラットフォームクラス (rt.jar 内のクラス) の場合と同じ特権が与えられます。このデフォルトの特権は、システムポリシーファイル (<java-home>/jre/lib/security/java.policy) で指定されていますが、適切なポリシーファイルのエントリ (「JDK でのアクセス権」を参照) を追加すれば、特定のオプションパッケージにオーバーライドできます。

なお、信頼できるエンティティーによりインストール型オプションパッケージの JAR ファイルに署名が付けられている場合、そのオプションパッケージには、署名を付けたエンティティーに関連付けられている特権が与えられます。

オプションパッケージのシーリング

JAR ファイルとパッケージは、同一バージョン内で整合性が保たれるように、オプションでシールすることができます。

JAR ファイル内のパッケージをシールした場合、そのパッケージ内で定義されているすべてのクラスは、同一の JAR ファイルが元になっていなければなりません。そうでない場合は、SecurityException がスローされます。

JAR ファイルをシールした場合、その JAR ファイルで定義されているすべてのパッケージは、特別に設定をオーバーライドしないかぎり、シールされます。

パッケージをシールするかどうかは、マニフェスト属性 Sealed で指定します。このマニフェスト属性は、truefalse の値をとります。大文字小文字は区別されません。次に例を示します。

Name: javax/servlet/internal/
Sealed: true
このように指定すると、javax.servlet.internal がシールされ、このパッケージに含まれるすべてのクラスは同一の JAR ファイルからロードされなければなりません。

この属性が指定されていない場合は、パッケージのシール属性は、そのパッケージが含まれる JAR ファイルのシール属性と同じになります。

JAR ファイルをシールするかどうかは、上と同じマニフェストヘッダー Sealed で指定します。このマニフェストヘッダーも、同じく truefalse の値をとります。次に例を示します。

Sealed: true
このように指定すると、このアーカイブに含まれるすべてのパッケージは、マニフェストエントリの中で Sealed 属性により明示的に設定をオーバーライドしないかぎり、シールされます。

この属性が指定されていない場合は、下位互換性を保つため、その JAR ファイルはシールされていないものとみなされます。このあと、システムはシール情報を見るため、パッケージのヘッダーのチェックを継続します。

パッケージをシールすると、パッケージ保護されたメンバーへのアクセスは、同一の JAR ファイルが元になるパッケージで定義されているクラスに制限されるため、パッケージのシールはセキュリティーの上でも重要です。

パッケージシーリングのチェックは、ダウンロード型オプションパッケージだけでなくインストール型オプションパッケージについても行われ、違反があった場合は SecurityException がスローされます。また、null パッケージはシールできないので、シールすべきクラスはその独自のパッケージ内に置く必要があります。 

オプションパッケージのセキュリティー

インストール型オプションパッケージのコードソース (<java-home>/lib/ext) には、事前に構成されたセキュリティーポリシーが割り当てられています。Sun の実装では、このディレクトリに置かれた JAR ファイルに与えられる正確な信頼度レベルは、次の標準のセキュリティーポリシー構成ファイルによって指定されます
<java-home>/lib/security/java.policy
デフォルトのポリシーは、インストール型オプションパッケージが、コアプラットフォームの一部である場合と同じように動作できるようにするためのものです。これは、インストール型オプションパッケージがネイティブコードをロードするという一般的な必要性に基づいています。

Java Security Model は、インストール型オプションパッケージのコードが信頼できないコードから呼び出された場合のために、ある種の安全策を提供しています。しかし、オプションパッケージのコードが特権ブロックを使用する場合は必ず、セキュリティー上の危険性がないかどうかコードを十分に確認する必要があります。

リモートからロードされるオプションパッケージで、正常な動作のため、アクセスチェックが行われるシステムサービス (ファイル入出力など) を使用する必要があるものについては、信頼できるエンティティーによる署名が付けられたものであるか、信頼できる場所からロードされたものでなければなりません。

Java プラットフォームのセキュリティー機能を利用するためのオプションパッケージやアプリケーションのコードを記述する方法の詳細については、Java セキュリティードキュメントを参照してください。

関連 API

Java プラットフォームのいくつかのクラスは、次のような拡張機能メカニズムをサポートします。

* この Web サイトで使用されている用語「Java 仮想マシン」または「JVM」は、Java プラットフォーム用の仮想マシンを表します。


Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.