拡張機能機構のアーキテクチャ |
注: オプションパッケージは、これまで「標準拡張機能」として知られてきたものの新しい名称です。拡張機能機構は、オプションパッケージの使用をサポートする、JDK および JRE の機能です。このドキュメントでは、オプションパッケージを扱うための Java プラットフォームの機構について説明します。オプションパッケージは、1 つまたは複数の JAR ファイルにまとめられたパッケージの集まりで、Java プラットフォームを拡張する API を実装します。オプションパッケージはプラットフォームを拡張して、仮想マシンが、クラスパスに存在しないクラスをプラットフォームのコア API のクラスとして検索し、ロードできるようにします。
オプションパッケージの実装は、Java プログラミング言語で記述されたコードですが、まれに、プラットフォーム固有のネイティブコードが含まれる場合もあります。さらに、プロパティ、地域対応のカタログ、イメージ、直列化されたデータ、およびその他のリソースなど、そのオプションパッケージに固有の各種リソースが含まれることもあります。
Internet Explorer や Netscape Navigator などのブラウザでは、オプションパッケージは Java Plug-in によってサポートされています。
オプションパッケージは、オープンで標準的な API を実装したものです (Sun が提供するオプションパッケージは、JavaServlet、Java3D、JavaManagement など)。例外もありますが、オプションパッケージの多くは javax.* の名前空間に割り当てられます。
アーキテクチャ
拡張機能機構は、次の要素を含むように設計されています。したがって通常、アプリケーションでは、必要なオプションパッケージ (より一般的な言い方をすれば、ライブラリ) を指定して、さらに提供する必要があります。システムは、インストールされているオプションパッケージ (およびライブラリ) がある場合は、それを選び、ない場合は、参照されているオプションパッケージ (およびライブラリ) クラスの検索とロードをアプリケーションのクラスローダに委譲します。
- JAR ファイルにまとめたオプションパッケージまたはアプリケーションは、ほかの JAR ファイルとの依存関係を宣言できるようになっています。 このため、アプリケーションを複数のモジュールで構成できます。
- クラスローディング機構を拡張して、インストール型オプションパッケージ (およびほかのライブラリ) からクラスを検索できるようになっています。検索に失敗すると、アプリケーションで指定したパスからクラスを検索します。
このアーキテクチャでは、アプリケーション、アプレット、およびサーブレットがそれら自体のクラスパスを拡張できるので、それらを複数の JAR ファイルとしてまとめ、配置することも可能になります。
それぞれのオプションパッケージまたはアプリケーションは、少なくとも 1 つの JAR ファイルで構成されます。JAR ファイルにはマニフェスト、コード、各種リソースが含まれることもあります。後述するように、この主 JAR ファイルには、ほかの JAR ファイルとの依存関係を記述するため、そのマニフェストに付加情報を含めることもできます。 The オプションパッケージを JAR ファイルにまとめるためには ZIP 互換のアーカイブツールも利用できますが、JDK に付属のコマンド行ツール jar を利用すると便利です。(jar ツールの参照ページ:[Windows][Solaris])
オプションパッケージまたはアプリケーションは、主 JAR ファイルから参照される別の JAR ファイルを参照することもあります。これらの JAR ファイルには、JAR ファイルごとに独自の依存関係情報を含めることもできます。
オプションパッケージを構成するパッケージは、オプションパッケージの実装時には、標準的なパッケージ命名規約に従って命名する必要があります。この命名規約は Java 言語仕様で大筋が示されていますが、ドメインの接頭辞はすべて大文字で指定するという規則はなくなりました。たとえば、COM.sun.server というパッケージ名は com.sun.server とも指定できます。アプリケーションとオプションパッケージは同じクラスローダを共有する場合があるので、名前の重複を避けるため、パッケージには一意の名前を付けることをお勧めします。
オプションパッケージの配置
オプションパッケージは、アプリケーションにバンドルする (バンドル型) 方法と、すべてのアプリケーションで使用できるように JRE にインストールする (インストール型) 方法があります。バンドル型オプションパッケージはアプリケーションと同じコードベースに置かれ、ネットワークアプリケーション (アプレット) の場合は自動的にダウンロードされます。したがって、バンドル型オプションパッケージは、「ダウンロード型」オプションパッケージと呼ばれる場合があります。インストール型オプションパッケージは、最初に使用されるときにロードされ、その実行環境で動作するすべてのアプリケーションによって共有されます。オプションパッケージをまとめる場合には、JAR ファイルのマニフェストはベンダーおよびバージョン情報を識別するために使用されます (「パッケージのバージョン管理の仕様」を参照)。
インストール型オプションパッケージのクラスは、同じ仮想マシン上のすべてのコードによって「共有」されます。したがって、インストール型オプションパッケージはそのプラットフォームの (rt.jar の) コアクラスに似ていますが、インストール型オプションパッケージは、後述するように、専用のクラスローダと事前に構成されたセキュリティポリシーを持ちます。
バンドル型オプションパッケージのクラスは、当該アプリケーション、アプレット、またはサーブレットのクラスローダだけが使用します。アプレットなどのネットワークアプリケーションの場合、バンドル型オプションパッケージは必要に応じて自動的にダウンロードされます。現時点では、クラスローダは特定のコードベースに関連付けられているので、同じコードベースに置かれたアプレットであれば実装 (JAR) を共有できます。
バンドル型オプションパッケージ
アプリケーションまたはオプションパッケージのマニフェストでは、必要なオプションパッケージ (およびその他のライブラリ) が含まれる JAR ファイルとディレクトリを参照する相対 URL を 1 つ以上指定できます。これらの相対 URL は、アプリケーションまたはオプションパッケージが含まれている JAR ファイルのロード元であるコードベースと相対的な位置関係にあるものとして扱われます。アプリケーション (より一般的には、JAR ファイル) は、必要なオプションパッケージ (およびライブラリ) の URL を、マニフェスト属性 Class-Path で指定します。この属性では、ホストの Java 仮想マシン* にインストールされたオプションパッケージの中から目的のオプションパッケージ (またはその他のライブラリ) の実装が見つからなかった場合に検索する URL を列挙します。この相対 URL には、アプリケーションまたはオプションパッケージが必要とするライブラリまたはリソースが含まれる JAR ファイルとディレクトリを含めることができます。「/」で終わらない URL は、JAR ファイルを参照しているものとみなされます。次に例を示します。
Class-Path ヘッダを複数指定することもできます。 複数指定した場合は、順に連結されます。Class-Path:servlet.jar infobus.jar acme/beans.jar images/現時点では、セキュリティ上の理由により、URL は JAR ファイルのコードベースから「相対的」に指定する必要があります。したがって、リモートオプションパッケージは、アプリケーションと同じコードベースを元にして指定します。将来的には、ほかの URL にある JAR ファイルを参照できるように、Java 2 プラットフォームの Security API の機能が利用できるようになる予定です。
それぞれの相対 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 [Windows] <java-home>/lib/ext [Solaris]<java-home> は、ランタイムソフトウェアがインストールされているディレクトリ (JRE のトップレベルディレクトリまたは JDK の jre ディレクトリ) を参照します。<arch> は、Solaris プロセッサアーキテクチャ (sparc または x86) を参照します。<java-home>\bin [Windows] <java-home>/lib/<arch> [Solaris]インストール型オプションパッケージは、さらに 1 つ以上の共有ライブラリ (.dll ファイルなど) と実行可能ファイルを含んでいます。ネイティブライブラリは、Windows と Solaris の両方で jre/lib/ext/<arch> ディレクトリに置かれます。Windows システムでは、<arch> は x86 です。jre/lib/ext/<arch> ディレクトリは、jre\bin (Windows) または jre/lib/<arch> (Solaris) の次に検索されます。
現時点では、ネイティブコードが含まれるオプションパッケージは、信頼できるコードか信頼できないコードかにかかわらず、実行時にネットワークコードにより仮想マシンにダウンロードすることはできません。ネイティブコードが含まれ、ネットワークアプリケーションとともにバンドルされているオプションパッケージは、JDK または JRE にインストールする必要があります。
デフォルトでは、この標準のディレクトリに置かれたインストール型オプションパッケージは信頼できます。つまり、このディレクトリに置かれたインストール型拡張機能には、コアプラットフォームクラス (rt.jar 内のクラス) の場合と同じ権限が与えられます。このデフォルトの権限はシステムポリシーファイルで指定されますが、適切なポリシーファイルエントリを追加することで、特定のオプションパッケージの権限をオーバーライドできます。
なお、信頼できるエンティティによりインストール型オプションパッケージの JAR ファイルに署名が付けられている場合、そのオプションパッケージには、署名を付けたエンティティに関連付けられている権限が与えられます。
システムプロパティ java.ext.dirs を使用すると、インストール型拡張機能を置く場所をほかにも指定できます。このプロパティには、インストール型拡張機能を検索するディレクトリを指定できます。 複数のディレクトリを指定する場合は、File.pathSeparatorChar で区切ります。このプロパティのデフォルトの設定値は、上に示したインストール型拡張機能の標準のディレクトリになっています。
JAR ファイルとパッケージは、同一バージョン内で整合性が保たれるように「シール」することができます。JAR ファイル内のパッケージをシールした場合、そのパッケージ内で定義されているすべてのクラスは、同一の JAR ファイルが元になっていなければなりません。そうでない場合は、SecurityException がスローされます。
JAR ファイルをシールした場合、その JAR ファイルで定義されているすべてのパッケージは、特別に設定をオーバーライドしないかぎり、シールされます。
パッケージをシールするかどうかは、マニフェスト属性 Sealed で指定します。 このマニフェスト属性は、true か false の値をとります。 大文字と小文字は区別されません。次に例を示します。
このように指定すると、javax.servlet.internal がシールされ、このパッケージに含まれるすべてのクラスは同一の JAR ファイルからロードされなければなりません。Name:javax/servlet/internal/ Sealed:trueこの属性が指定されていない場合は、パッケージのシール属性は、そのパッケージが含まれる JAR ファイルのシール属性と同じになります。
JAR ファイルをシールするかどうかは、上と同じマニフェストヘッダ Sealed で指定します。 このマニフェストヘッダも、同じく true か false の値をとります。次に例を示します。
このように指定すると、このアーカイブに含まれるすべてのパッケージは、マニフェストエントリの中で Sealed 属性により明示的に設定をオーバーライドしないかぎり、シールされます。Sealed:trueこの属性が指定されていない場合は、下位互換性を保つため、そのモジュールはシールされていないものとみなされます。このあと、システムはシール情報を見るため、パッケージのヘッダのチェックを継続します。
パッケージをシールすると、パッケージ保護されたメンバへのアクセスは、同一の JAR ファイルが元になるパッケージで定義されているクラスに制限されるため、パッケージのシールはセキュリティの上でも重要です。
パッケージシーリングのチェックは、ダウンロード型オプションパッケージだけでなくインストール型オプションパッケージについても行われ、違反があった場合は SecurityException がスローされます。また、null パッケージはシールできないので、シールすべきクラスはその独自のパッケージ内に置く必要があります。
インストール型オプションパッケージのコードソース (<java-home>/lib/ext) には、事前に構成されたセキュリティポリシーが割り当てられています。Sun の実装では、このディレクトリに置かれた JAR ファイルに与えられる正確な信頼度レベルは、次の標準のセキュリティポリシー構成ファイルによって指定されます。デフォルトのポリシーは、インストール型オプションパッケージが、コアプラットフォームの一部である場合と同じように動作できるようにするためのものです。これは、インストール型オプションパッケージがネイティブコードをロードするという一般的な必要性に基づいています。<java-home>/lib/security/java.policyJava Security Model は、インストール型オプションパッケージのコードが信頼できないコードから呼び出された場合のために、ある種の安全策を提供しています。しかし、オプションパッケージのコードが特権ブロックを使用する場合は必ず、セキュリティ上の危険性がないかどうかコードを十分に確認する必要があります。
リモートからロードされるオプションパッケージで、正常な動作のため、アクセスチェックが行われるシステムサービス (ファイル入出力など) を使用する必要があるものについては、信頼できるエンティティによる署名が付けられたものであるか、信頼できる場所からロードされたものでなければなりません。
Java 2 プラットフォームのセキュリティ機能を利用するためのオプションパッケージやアプリケーションのコードを記述する方法の詳細については、Java 「セキュリティ」を参照してください。
拡張機能機構は、Java 2 プラットフォームの次のクラスでサポートされています。
- public class java.lang.ClassLoader (変更)
このクラスローダ委譲モデルは、クラスまたはリソースのロード時に、それをローカルにロードするのを試みる前にいつでも必ず最初に検索される、「親」クラスローダを指定できるようにするものです。新しいクラスローダの実装では、クラスとリソースをローカルにロードする方法を指定するため、findClass と findResource の 2 つのメソッドがオーバーライドされています。
委譲モデルでは、クラスとリソースのロードのための一貫性があって良く定義された検索ポリシーが提供されており、クラスローダの実装が容易に行えるようになっています。これらの変更は下位互換性を持っており、既存のクラスローダの実装には影響しません。しかし、独自のクラスローダを作成するとともにオプションパッケージを利用するアプリケーションの場合は、委譲モデルを使用しなければなりません。
- getSystemClassLoader
委譲のためのシステムクラスローダを返します。これは、新しい ClassLoader のインスタンスに対するデフォルト委譲の親で、通常このクラスローダはアプリケーションの起動に使用されます。- loadClass
クラスがすでにロードされている場合は、単にそれを返します。クラスがロードされていない場合は、親クラスローダ (親が指定されていない場合は、ブートストラップクラスローダと呼ばれる仮想マシンの組み込みクラスローダ) からクラスのロードを試みます。それでも見つからない場合は、findClass メソッドを呼び出して、クラスをローカルにロードします。
- findClass
指定されたクラスをこのクラスローダから探します。このメソッドは、新しいクラスローダの実装の中でオーバーライドしてください。このメソッドのデフォルトの実装は、ClassNotFoundException をスローします。
- getResource
親クラスローダ (親が指定されていない場合はブートストラップクラスローダ) からリソースの取得を試みます。それでもリソースが見つからない場合は、getLocalResource メソッドを呼び出して、リソースをローカルにロードします。
- findResource
指定されたリソースをこのクラスローダから探します。このメソッドは、新しいクラスローダの実装でオーバーライドしてください。このメソッドのデフォルトの実装は、null を返します。
- getResources
指定されたリソース名に一致するすべてのリソースの URL を列挙したリストを返します。このリストには、親クラスローダが返したすべての一致リソースに findResources が返した列挙を続けたものが含まれます。
- findResources
指定された名前に一致する全ローカルリソースの URL を列挙したリストを返します。このメソッドは、新しいクラスローダの実装でオーバーライドしてください。このメソッドのデフォルトの実装は、null を返します。
簡単なネットワーククラスローダの例を次に示します。
public class NetClassLoader extends ClassLoader { URL url; public NetClassLoader(URL url, ClassLoader parent) { super(parent); this.url = url; } protected Class findClass(String name) throws ClassNotFoundException { .. load class from URL ... } protected URL findResource(String name) { try { URL u = new URL(url, name); if (u.openConnection() != null) { return u; } else { return null; } } catch (java.net.MalformedURLException mue) { // handle exception } catch (java.io.IOException ioe) { // handle exception } } }この例では、指定された URL をチェックする前に、クラスとリソースを親クラスローダ (親が指定されていない場合はブートストラップクラスローダ) から探します。クラスとリソースは、前述した委譲モデルに従ってロードされます。public class java.lang.Package isSealed メソッドを使用すると、パッケージがシールされているかどうかをチェックでき、シールされている場合は true が返されます。このメソッドの 2 番目の形式では、URL をとり、指定された URL についてパッケージがシールされていれば true を返します。このメソッドは、クラスローダの実装の中で使い、新しいクラスのロード時に、現在シールされているパッケージを見失うことがないようにする目的で使用できます。
public class java.net.URLClassLoader このクラスでは、オプションパッケージとアプリケーションのための基本的なクラスローダサポートが提供されています。このクラスでは、クラスとリソースの 1 つまたは複数のベース URL を検索するため、findClass メソッドと findResource メソッドがともにオーバーライドされています。URL は必要になるまで開かれないため、検索はただちに行われるわけではありません。
URLClassLoader は、クラスとリソースのロードに使われる URL の検索パスを管理します。最初、検索パスはクラスローダが作成されたときに指定された URL に設定されますが、前述したように、マニフェスト属性 Class-Path によって拡張できます。
URLClassLoader は、Java バージョン管理の仕様で規定されている、バージョン管理のためのマニフェスト属性をすべてサポートしています。
さらに、以下の主要なマニフェスト属性がサポートされています。
- Main-Class: <classname> (デフォルト値なし)
アプリケーションの主要なクラスを指定します。この属性は、アプリケーションの JAR ファイルの呼び出しに使用されます。
- Class-Path: <urls..>(デフォルト値なし)
クラスとリソースをロードするため、JAR ファイルとディレクトリの URL のローカル検索パスを相対 URL で指定します。「/」で終わらない URL は、JAR ファイルを参照しているものとみなされます。
- Sealed: <true|false> (デフォルト値: false)
「null」パッケージを除き、この JAR ファイルで定義されているすべてのパッケージがシールされます。「null」パッケージをシールすることはできません。このヘッダは、個々のパッケージのシールにも使用できます。
* この Web サイトで使用されている用語「Java 仮想マシン」または「JVM」は、Java プラットフォーム用の仮想マシンを表します。
Copyright © 1997-1999 Sun Microsystems, Inc.All Rights Reserved.
コメントの送付先: Java ソフトウェア |