Java

JavaTM プラットフォーム V 1.2 での拡張機能とアプリケーションのサポート

目次

はじめに

このドキュメントでは、拡張機能を扱うための Java プラットフォームの新しい機構について説明します。拡張機能は、1 つまたは複数の JAR ファイルにまとめられたパッケージの集まりで、Java プラットフォームを拡張する API を実装します。拡張クラスはプラットフォームを拡張して、Virtual Machine が、クラスパスに存在しないクラスをプラットフォームのコア API のクラスであるかのように発見し、ロードできるようにします。

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

Internet Explorer や Netscape NavigatorTM などのブラウザでは、拡張機能は Java Plug-in によってサポートされます。

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

拡張機能機構

アーキテクチャ

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

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

それぞれの拡張機能またはアプリケーションは、少くとも 1 つの JAR ファイルで構成されます。JAR ファイルにはマニフェスト、コード、各種リソースが含まれることもあります。後述するように、この主 JAR ファイルには、ほかの JAR ファイルとの依存関係を記述するため、そのマニフェストに付加情報を含めることもできます。拡張機能を JAR ファイルにまとめるためには ZIP 互換のアーカイブツールも利用できますが、JDK ソフトウェアに付属のコマンド行ツール jar を利用すると便利です。(jar ツール の参照ページ: [Win32][Solaris])

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

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

拡張機能の配置

拡張機能は、アプリケーションにバンドルする (バンドル型) 方法と、すべてのアプリケーションで使用できるように JRE にインストールする (インストール型) 方法があります。バンドル型拡張機能はアプリケーションと同じコードベースに置かれ、ネットワークアプリケーション (アプレット) の場合は自動的にダウンロードされます。したがって、バンドル型拡張機能は、「ダウンロード型」拡張機能と呼ばれる場合があります。インストール型拡張機能は、最初に使用されるときにロードされ、その JRE 上で動作するすべてのアプリケーションによって共有されます。

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

インストール型拡張機能のクラスは、同じ Java 1.2 Virtual Machine 上のすべてのコードによって「共有」されます。したがって、インストール型拡張機能はそのプラットフォームの (rt.jar の) コアクラスに似ていますが、インストール型拡張機能は、後述するように、専用のクラスローダと事前に構成されたセキュリティポリシーを持ちます。

バンドル型拡張機能のクラスは、当該アプリケーション、アプレット、またはサーブレットのクラスローダだけが使用します。アプレットなどのネットワークアプリケーションの場合、バンドル型拡張機能は必要に応じて自動的にダウンロードされます。現時点では、クラスローダは特定のコードベースに関連付けられているので、同じコードベースに置かれたアプレットであれば実装 (JAR) を共有できます。

バンドル型拡張機能

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

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

Class-Path: servlet.jar infobus.jar acme/beans.jar images/

Class-Path ヘッダを複数指定することもできます。複数指定した場合は、順に連結されます。

現時点では、セキュリティ上の理由により、URL は JAR ファイルのコードベースから「相対的」に指定する必要があります。したがって、リモート拡張機能は、アプリケーションと同じコードベースを元にして指定します。将来的には、ほかの URL にある JAR ファイルを参照できるように、Java 1.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 x.jar b.jar
もちろん、x.jar に依存情報が含まれる場合は、依存ファイルはこれと同じ規則に従って追加されます。あとに続く URL についても同様です。実際の実装では、JAR ファイルの依存関係は先に処理されるのではなく、JAR ファイルは実際に必要になったときまで開かれません。

インストール型拡張機能

Sun による Java 1.2 Virtual Machine の実装では、インストール型拡張機能の JAR ファイルは、次の標準のローカルコードソースに置かれます。
<java-home>¥lib¥ext			[Win32]
<java-home>/lib/ext			[Solaris]
そのネイティブコードライブラリは、存在する場合は、次の場所に置かれます。
<java-home>¥bin				[Win32]
<java-home>/lib/<arch>		        [Solaris]
<java-home> は、ランタイムソフトウェアがインストールされているディレクトリ (JRE のトップレベルディレクトリまたは JDK ソフトウェアの jre ディレクトリ) を参照します。<arch> は、Solaris プロセッサアーキテクチャ (sparc または i386) を参照します。

インストール型拡張機能は、さらに 1 つ以上の共有ライブラリ (.dll ファイルなど) と実行可能ファイルを含んでいます。また、ネイティブライブラリは、Win32 と Solaris の両方の jre/lib/ext/<arch> ディレクトリに置かれます。Win32 システムでは <arch>i386 です。jre/lib/ext/<arch> ディレクトリは、jre¥bin (win32) または jre/lib/<arch> (Solaris) の次に検索されます。

現時点では、ネイティブコードが含まれる拡張機能は、信頼できるコードか信頼できないコードかにかかわらず、実行時にネットワークコードにより Virtual Machine にダウンロードすることはできません。ネイティブコードが含まれ、ネットワークアプリケーションにバンドルされた拡張機能は、JRE または JDKTM ソフトウェアにインストールする必要があります。

デフォルトでは、この標準のディレクトリに置かれたインストール型拡張機能は信頼されます。つまり、このディレクトリに置かれたインストール型拡張機能には、コアプラットフォームクラス (rt.jar 内のクラス) の場合と同じ権限が与えられます。このデフォルトの権限はシステムポリシーファイルで指定されますが、適切なポリシーファイルエントリを追加することで、特定の拡張機能の権限をオーバーライドできます。

なお、信頼できるエンティティによりインストール型拡張機能の JAR ファイルに署名が付けられている場合、その拡張機能には、署名を付けたエンティティに与えられている権限が与えられます。

システムプロパティ java.ext.dirs を使用すると、インストール型拡張機能を置く場所をほかにも指定できます。このプロパティには、インストール型拡張機能を検索するディレクトリを指定できます。複数のディレクトリを指定する場合は、File.pathSeparatorChar で区切ります。このプロパティのデフォルトの設定値は、上に示したインストール型拡張機能の標準のディレクトリになっています。

拡張機能のシーリング

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 の rt.jar では、sun.iojava.text.resources の 2 つのパッケージを除く標準コア Java パッケージすべてがシールされています。

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

拡張機能のセキュリティ

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

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

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

新しいセキュリティ機能を利用して拡張機能やアプリケーションのコードを記述する方法の詳細については、Java 1.2「セキュリティ」を参照してください。

API の詳細

バージョン 1.2 のプラットフォームでは、新しい拡張機能機構をサポートするため、以下のクラスが変更または追加されています。

java コマンドの変更

概要

バージョン 1.2 の JRE および JDK ソフトウェアでは、拡張機能を使用するスタンドアロンアプリケーションをサポートするため、java コマンドに変更が加えられました。これまでは、アプリケーションクラスはシステムクラスローダからロードされていましたが、新しい java コマンドでは、アプリケーションをロードするために URLClassLoader のインスタンスが作成されます。委譲の親は、インストール型拡張機能のロードのためシステムが管理する共用クラスローダに設定されます。使用されるアプリケーションクラスローダは、アプリケーションが使用するインストール型拡張機能とバンドル型拡張機能のどちらのロードも処理します。

アプリケーションのクラスパス

アプリケーションをロードするために、URLClassLoader のインスタンスを作成するときには、使用される URL の検索パスは、java.class.path プロパティから読み出されます。このプロパティは、アプリケーションのクラスとリソースをロードするアプリケーションのクラスパスを指定するものです。クラスまたはリソースのロード時、クラスローダは最初にシステムクラスパスを探し、次にインストール型拡張機能を、最後にアプリケーションのクラスパスを探します。

この変更の結果、java.class.path プロパティにはブートストラップクラスパスからのエントリは格納されないようになりました。システムクラスパスは、システムプロパティ sun.boot.class.path から別個に得られるようになりました。

環境変数 CLASSPATH は、java.class.path プロパティのデフォルト値を指定するものです。この環境変数を設定しない場合、java.class.path のデフォルト値は現在のディレクトリに設定されます。

-classpath オプションは、java.class.path プロパティを簡単に設定するための手段となっています。以前は、このオプションはシステムクラスの検索パスをオーバーライドするために使用されていました。新しい java コマンドでは、システムクラスパスを設定する必要はありません。

-cp オプション

-cp オプションは、jre コマンドでだけ使用できるオプションでしたが、java コマンドにも追加されました。ただし、新しい java コマンドではシステムクラスパスを設定する必要はないため、このオプションは単に -classpath の別名になっています。

たとえば、次の 3 つのコマンドはどれも同じ意味です。

	java -classpath foo.jar:bar Foo
	java -Djava.class.path=foo.jar:bar Foo
	java -cp foo.jar:bar Foo

セキュリティプロパティの設定

デフォルトでは、アプリケーションはセキュリティマネージャなしで起動され、ポリシーのチェックは有効になりません。この動作は、すべてがシステムクラスパスからロードされる以前のコマンドの動作と同じです。

アプリケーションの起動時にセキュリティマネージャをインストールするには、次のように、コマンド行オプション -Djava.security.manager を使用します。

        java -Djava.security.manager Foo

デフォルトのシステムポリシーファイルは、{java.home}/lib/security/java.policy です。{user.home}/.java.policy のポリシーファイルを使用することで、ユーザは個々にデフォルトのポリシーファイルを強化できます。デフォルトのポリシーに加えて使用するポリシーファイルを指定するには、次のようにします。

        java -Djava.security.policy=somePolicy Foo

ポリシーファイルの詳細は、「Default Policy Implementation and Policy File Syntax」 を参照してください。

-jar オプション

JAR ファイルにまとめられたアプリケーションを簡単に実行できるように、java アプリケーション起動ツールに -jar オプションが新たに追加されました。このオプションを使用すると、JAR ファイル内のアプリケーションを java コマンドで直接実行できます。

-jar オプションを使用するときは、java.class.path プロパティに実行する JAR ファイルを設定すると、これが -classpath コマンド行オプションまたは -cp コマンド行オプションで指定したほかの定義をオーバーライドします。このようにすることで、JAR ファイルのマニフェストが参照され、マニフェスト属性 Main-Class で指定されたアプリケーションのメインクラスの名前が検出されます。たとえば、server.jar のマニフェストで次のような属性が指定されているとします。

Main-Class: com.sun.server.Main
この場合、次のどちらのコマンド行でも、server.jar を実行できます。
java -jar server.jar
java -Djava.class.path=server.jar com.sun.server.Main

実行可能 JAR ファイル

Win32 システムでは、インストールプログラムが JAR ファイルと、デフォルトで対応付けられます。その結果として、デスクトップ上で JAR ファイルをダブルクリックするだけで java -jar により JAR ファイルが自動的に起動されます。アプリケーションにバンドルされた、アプリケーションが依存している拡張機能も自動的にロードされます。このため、Win32 システムではエンドユーザにとって JRE が使いやすくなっています。

Solaris 2.6 のカーネルは、JAR ファイルを表す特別な「マジック」ナンバーを認識するようにすでに拡張が施されており、java -jar で JAR ファイルを Solaris のネイティブ実行可能ファイルであるかのように起動できるようになっています。JAR ファイルにまとめられたアプリケーションも、コマンド行から、または CDE デスクトップ上でアイコンをクリックすることで直接実行できます。

jre コマンド

JRE 1.2 では jre コマンドはなくなり、java ツールに併合されました。JRE 1.2 でも使用できる唯一の環境変数は CLASSPATH で、この環境変数は、java ツールの -classpath オプションか -cp オプションを使用してオーバーライドできるようになっています。新しい java コマンドでは、JRE のシステムクラスパスの設定に使用されていた -cp オプションは -classpath と同じ意味になりました。

互換性

独自のクラスローダまたはセキュリティマネージャをインストールするアプリケーションは、バージョン 1.2 のプラットフォームに対応するようにアップデートされるまで、新しい java コマンドでは実行できない可能性があります。このようなアプリケーションは、バージョン 1.2 の JRE および JDK ソフトウェアで導入された新しいセキュリティ機能と委譲クラスローダを使用するよう、アップデートする必要があります。

互換性のため、バージョン 1.1 の Java プラットフォームと同じようにシステムクラスパスからアプリケーションを実行する、旧式の起動コマンド oldjava が用意されています。しかし、oldjava コマンドでは拡張機能はサポートされていません。


Copyright © 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.

コメントの送付先: Java ソフトウェア
Sun