JAR ファイルの仕様
目次
はじめに
JAR ファイルは普及している ZIP ファイル形式に基づくファイル形式で、多数のファイルを 1 つにまとめるために使用されます。 JAR ファイルは、基本的にはオプションの META-INF ディレクトリを格納する ZIP ファイルです。JAR ファイルは、コマンド行 jar ツールを使うか、Java プラットフォームで java.util.jar API を使って作成できます。JAR ファイルの名前には制約がないため、各プラットフォームで許可されているファイル名を使うことができます。
多くの場合、JAR ファイルは、単純な Java のクラスファイルまたはリソースのアーカイブではありません。JAR ファイルは、アプリケーションおよび拡張機能の構築ブロックとして使います。META-INF ディレクトリが存在する場合は、セキュリティ、バージョン管理、拡張機能、サービスなど、パッケージおよび拡張機能の構成データを格納するときに使います。
META-INF ディレクトリ
Java 2 プラットフォームでは、アプリケーション、拡張機能、クラスローダ、およびサービスが構成されるときに、META-INF ディレクトリから次のファイルとディレクトリの認識および解釈が行われます。
拡張機能およびパッケージ関連のデータの定義に使うマニフェストファイル
このファイルは、jar ツールの新しいオプション「-i」によって生成されます。アプリケーションまたは拡張機能に定義されているパッケージの位置情報が格納されます。JarIndex 実装に組み込まれており、クラスのロード処理を速くするためにクラスローダによって使われます。
JAR ファイルの署名ファイルです。 「x」は、ベースファイル名を表します。
同じベースファイル名を持つ署名ファイルに関連付けられた署名ブロックファイル。対応する署名ファイルのデジタル署名が格納されます。
サービスプロバイダ構成ファイルがすべて格納されます。
名前-値ペアおよびセクション
各構成ファイルの内容を詳細に設定する前に、形式の規則をいくつか定義する必要があります。ほとんどのケースで、マニフェストファイルまたは署名ファイルに含まれる情報は、RFC822 で規定されるいわゆる「名前:値」ペアとして表されます。 「名前:値」ペアは、ヘッダまたは属性とも呼ばれます。
名前-値ペアのグループを「セクション」と呼びます。セクションはほかのセクションと空白行で分けられます。
バイナリデータは、どの形式であれ base64 で表されます。行の長さが 72 バイ トを超えるようなバイナリデータについては継続が必要です。バイナリデータの例はダイジェストおよび署名です。
実装によっては、65535 バイトまでのヘッダ値がサポートされます。
このドキュメントの仕様には同一の文法が使われており、終端記号は固定幅のフォントで示され、終端以外の記号はイタリック書体で示されています。
仕様:
section: *header +newline
nonempty-section: +header +newline
newline: CR LF | LF | CR (not followed by LF)
header: name :value
name: alphanum *headerchar
value: SPACE *otherchar newline *continuation
continuation: SPACE *otherchar newline
alphanum: {A-Z} | {a-z} | {0-9}
headerchar: alphanum | - | _
otherchar: any UTF-8 character except NUL, CR and LF
; Also:To prevent mangling of files sent via straight e-mail, no
; header will start with the four letters "From".
上の仕様で定義されている終端以外の記号は、以降の仕様で使われています。
JAR マニフェスト
概要
JAR ファイルマニフェストは、メインセクションと各 JAR ファイルエントリの複数の個別セクションで構成され、それぞれ改行文字で区切られています。メインセクションおよび個別セクションは、すでに説明したセクションの構文に準拠しています。各セクションには、固有の制約と規則があります。
メインセクションには、JAR ファイル自体のセキュリティと構成情報以外に、その JAR ファイルが使われているアプリケーションまたは拡張機能のセキュリティと構成情報を指定します。また、各マニフェストエントリに適用されるメイン属性も定義します。 メインセクションの属性に、「Name」と同じ名前を付けることはできません。メインセクションは、空白行で終わります。
個別セクションには、この JAR ファイルに格納されているパッケージまたはファイルのさまざまな属性を定義します。アーカイブ内のすべてのファイルをマニフェストのエントリにリストする必要はありませんが、署名するすべてのファイルはリストする必要があります。マニフェストファイル自体はリストしないでください。各セクションは、「Name」という名前の属性で始まる必要があります。この属性の値は、ファイルを起点とした相対パス、またはアーカイブの外部のデータを参照する絶対 URL でなければなりません。
1 つのファイルエントリに複数の個別セクションがある場合は、これらのセクションの属性はマージされます。特定の属性の値がセクションによって異なる場合は、最後のセクションの値が認識されます。
理解できない属性は無視されます。アプリケーションによって使われる実装固有の情報に、理解できない属性が含まれていることがあります。
マニフェストの仕様
manifest-file: main-section newline *individual-section
main-section: version-info newline *main-attribute
version-info: Manifest-Version :version-number
version-number : digit+{.digit+}*
main-attribute: (any legitimate main attribute) newline
individual-section: Name :value newline *perentry-attribute
perentry-attribute: (any legitimate perentry attribute) newline
newline : CR LF | LF | CR (not followed by LF)
digit: {0-9}
上の仕様では、メインセクションに指定した属性はメイン属性、個別セクションに指定した属性はエントリ別属性として参照されます。属性によっては、メインセクションと個別セクションの両方で指定できます。 この場合、そのエントリでは、メイン属性の値はエントリ別属性の値によってオーバーライドされます。 2 つのタイプの属性は、以下のように定義されます。
メイン属性
メイン属性は、マニフェストのメインセクションに指定されている属性です。メイン属性は、次のグループに分類されます。
マニフェストファイルのバージョンを定義する。 値は、上記の仕様に定義されている正当なバージョン番号
- Created-By:
このマニフェストファイルが生成される Java 実装のバージョンおよびベンダーを定義する。 この属性は、jar ツールによって生成される
- Signature-Version:
jar ファイルの署名のバージョンを定義する。 値は、有効な バージョン番号文字列でなければならない
- Class-Path:
この属性の値には、このアプリケーションまたは拡張機能に必要な拡張機能またはライブラリの相対 URL を指定する。URL は 1 つ以上の空白で区切る。 アプリケーションまたは拡張機能のクラスローダでは、この属性の値を使って内部検索パスが構築される
- スタンドアロンアプリケーションに対して定義する属性。
この属性は、Java ランタイムから「java -jar x.jar」によって直接呼び出された実行可能 jar ファイルに含まれる、スタンドアロンアプリケーションによって使われる
- Main-Class:
この属性の値には、起動時に起動ツールによってロードされるメインアプリケーションのクラスの相対パスを定義する。この値には、クラス名に拡張子「.class」が付いていてはならない
- アプレットに対して定義する属性。
この属性は、JAR ファイルに含まれるアプレットによって使われる。 このアプレットに必要な拡張機能の要件、バージョン、および位置情報を定義する。「拡張機能のバージョン管理」 を参照)
- Extension-List:
この属性には、このアプレットに必要な拡張機能を指定する。この属性に指定されている各拡張機能では、アプレットに必要な拡張機能のバージョンとベンダーを指定するときに、追加属性を使用できる
- <extension>-Extension-Name :
この属性には、拡張機能の固有名を指定する。 Java Plug-in によって、インストール済みの拡張機能のマニフェスト内の Extension-Name 属性とこの属性の値が比較され、その拡張機能がインストールされているかどうかが確認される
- <extension>-Specification-Version
この属性には、アプレットに必要な拡張機能仕様のバージョンの最小値を指定する。 Java Plug-in によって、インストール済みの拡張機能の Specification-Version 属性とこの属性の値が比較され、その拡張機能が最新のものであるかどうかが確認される
- <extension>-Implementation-Version
この属性は、アプレットに必要な実装のバージョン番号の最小値を指定する。 Java Plug-in では、インストールされている拡張機能の Implementation-Version 属性とこの属性の値が比較され、新しい実装をダウンロードする必要があるかどうかが検査される
- <extension>-Implementation-Vendor-Id
アプレットに特定のベンダーの実装が必要な場合は、この属性を使って拡張機能の実装のベンダーを識別できる。 Java Plug-in によって、インストール済みの拡張機能の Implementation-Vendor-Id 属性とこの属性の値が比較される
- <extension>-Implementation-URL
この属性には、必要なバージョンの拡張機能がインストールされていない場合に、最新バージョンの拡張機能を取得するときに使う URL を指定する
- 拡張機能の識別に対して定義する属性。
この属性は、拡張機能の一意の識別を定義するときに拡張機能によって使われる
- Extension-Name:
この属性には、Jar ファイル内に格納されている拡張機能の名前を指定する。名前は、拡張機能を構成するメインパッケージの名前など、一意の識別子でなければならない
- 拡張機能およびパッケージのバージョン管理とシーリング情報に対して定義する属性。
この属性には、JAR ファイルが使われている拡張機能の機能を定義する。 属性の値は JAR ファイル内のすべてのパッケージに適用される。ただし、エントリ別属性によってオーバーライドされることがある
- Implementation-Title:
拡張機能の実装のタイトルを定義する文字列
- Implementation-Version :
拡張機能の実装のバージョンを定義する文字列
- Implementation-Vendor :
拡張機能の実装を管理するベンダーを定義する文字列
- Implementation-Vendor-Id :
拡張機能の実装を管理するベンダーを一意に定義する文字列 ID
- Implementation-URL :
拡張機能の実装をダウンロードできる URL を定義する
- Specification-Title :
拡張機能の仕様のタイトルを定義する文字列
- Specification-Version:
拡張機能の仕様のバージョンを定義する文字列
- Specification-Vendor :
拡張機能の仕様を管理するベンダーを定義する文字列
- Sealed:
この JAR ファイルがシールされるかどうかを定義する。値は「true」または「false」で、大文字と小文字は区別されない。「true」に設定した場合は、JAR ファイル内のパッケージは、個別に定義しない限り、すべてデフォルトでシールされる
エントリ別属性
エントリ別属性は、そのマニフェストエントリが関連付けられている個別の JAR ファイルエントリにだけ適用されます。 メインセクションに同じ属性がある場合は、メイン属性の値はエントリ別属性の値によってオーバーライドされます。たとえば、JAR ファイル a.jar には、次のコンテンツがマニフェストに定義されています。
この場合、foo.bar パッケージを除き、a.jar 内に保管されているパッケージがすべてシールされます。
エントリ別属性は、次のグループに分類されます。
- ファイルのコンテンツに対して定義する属性:
- Content-Type:
この属性は、JAR ファイルの特定のファイルエントリに対して、データの MIME 形式およびサブタイプを指定するときに使われる。値は、「タイプ/サブタイプ」の形式の文字列でなければならない。たとえば、「image/bmp」は、サブタイプが bmp (ビットマップを表す) のイメージ形式である。これは、このファイルエントリが、ビットマップとして格納されたデータを持つイメージであることを示す。MIME 形式の定義の説明および定義については、RFC 1521 および 1522 を参照
- パッケージのバージョン管理およびシーリング情報に対して定義する属性:
拡張機能パッケージのバージョン管理およびシーリング情報を定義する。メイン属性に定義されている属性を参照。 エントリ別属性として使う場合は、メイン属性はオーバーライドされる。ただし、マニフェストエントリに指定したファイルにだけ適用される
- Beans オブジェクトに対して定義する属性:
- Java-Bean:
特定の jar ファイルエントリが、Java Beans オブジェクトかどうかを定義する。 値は「true」または「false」で、大文字と小文字は区別されない
- 署名に対して定義する属性:
以下の属性は、署名と検証の目的で使われる。詳細は以下のとおり
- x-Digest-y:
この属性の名前には、対応する jar ファイルエントリのダイジェスト値の計算に使われるダイジェストアルゴリズムの名前を指定する。この属性の値には、実際のダイジェストの値が格納される。 接頭辞の「x」にはアルゴリズム名を指定し、オプションの接尾辞「y」にはダイジェスト値の検証基準の言語を指定する
- Magic:
この属性は、オプションで、マニフェストエントリに指定したダイジェスト値をベリファイアが計算する方法を指定するために、アプリケーションで使われる。 値には、コンマで区切られたコンテキスト固有の文字列を指定する。詳細は、以降の説明を参照
署名付き JAR ファイル
概要
JAR ファイルに署名するには、コマンド行 jarsigner ツールを使うか、java.security API を直接使います。jarsigner ツールを使って JAR ファイルに署名した場合は、ファイルエントリごとに署名されます。java.security API を使った場合は、JAR ファイルのサブセットに署名されます。 署名された JAR ファイルは、ファイルのマニフェストが更新され、META-INF ディレクトリに署名ファイルと署名ブロックファイルが追加されていますが、それ以外の内容は元の JAR ファイルと同じです。 jarsigner を使わない場合は、署名プログラムは署名ファイルと署名ブロックファイルの両方を構築する必要があります。
署名付き JAR ファイルのファイルエントリが署名されると、そのエントリが以前にマニフェスト内に存在していなかった場合は、エントリ単位にマニフェストエントリが作成されます。各マニフェストエントリには、1 つまたは複数のダイジェスト属性とオプションの Magic 属性をリストします。
署名ファイル
各署名者は、拡張子が .SF の署名ファイルによって表されます。このファイルの大部分は、マニフェストファイルと同じです。このファイルは、メインセクションといくつかの個別エントリで構成されます。メインセクションの情報は署名者が定義しますが、特定の jar ファイルエントリ固有の情報ではありません。個別エントリの名前は、マニフェストファイル内にも定義する必要があります。各個別エントリには、少なくともマニフェストファイルの対応するエントリのダイジェストが含まれている必要があります。
マニフェストファイルに表示されるが署名ファイルには表示されないパスまたは URL は、計算に使用されません。
署名の検証
マニフェストが最初に分析されるとき、署名が最初に検証されます。この検証結果を効率化のために記録できます。これは実際のアーカイブファイルでなく、署名自体を検証するだけです。
ファイルを検証するためには、署名ファイルのダイジェスト値をマニフェストファイルの対応するエントリから計算したダイジェスト値と比較します。 次に、マニフェストファイルのダイジェストの値を、「Name:」属性から参照される実際のデータ (相対ファイルパスまたは URL) から計算されたダイジェストと比較します。
マニフェストファイルの例:
Manifest-Version:1.0
Created-By:1.3 (Sun Microsystems, Inc)
Name:common/class1.class
MD5-Digest: (base64 representation of MD5 digest)
Name:common/class2.class
MD5-Digest:(base64 representation of MD5 digest)
SHA-Digest:(base64 representation of SHA digest)
対応する署名ファイルは次のようになります。
Signature-Version: 1.0
Name:common/class1.class
MD5-Digest:(base64 representation of MD5 digest)
Name:common/class2.class
MD5-Digest:(base64 representation of MD5 digest)
Magic 属性
特定のマニフェストエントリ上で署名を有効化するためにもう 1 つ必要なのは、そのエントリのマニフェストエントリ内の Magic キーペア値の値をベリファイアが理解することです。
Magic 属性はオプションですが、パーサがそのエントリの署名を検証する場合は、エントリの Magic キーの値を理解する必要があります。
Magic 属性の値は、コンマで区切られたコンテキスト固有の文字列のセットです。コンマの前後の空白は無視されます。大文字小文字も無視されます。Magic 属性の正確な意味はアプリケーションによって異なります。これらの属性は、マニフェストエントリに含まれるハッシュ値の計算方法を示し、そのため署名の正しい検証には欠くことのできないものです。このキーワードは、動的または埋め込みコンテンツ、多国語ドキュメント用の複数ハッシュなどに使用します。
以下に、マニフェストファイルでの Magic 属性の使用例を 2 つ示します。
Name:http://www.scripts.com/index#script1
SHA-Digest:(base64 representation of SHA hash)
Magic:JavaScript, Dynamic
Name:http://www.tourist.com/guide.html
SHA-Digest:(base64 representation of SHA hash)
SHA-Digest-French:(base64 representation of SHA hash)
SHA-Digest-German:(base64 representation of SHA hash)
Magic:Multilingual
最初の例では、これら Magic の値は http 問い合わせの結果がドキュメント自身ではなく、ドキュメントに埋め込まれたスクリプトであり、またそのスクリプトが動的に生成されるということを示します。この 2 つの情報は、マニフェストのダイジェスト値と比較し、有効な署名と比較するハッシュ値の計算方法を示します。
第 2 の例では、Magic 値は検索されたドキュメントの内容は特定の言語であるという合意を示し、検証のためのダイジェストの値は検索されたドキュメントを記述する言語に依存することを示します。
デジタル署名
デジタル署名とは、署名された .SF 署名ファイルです。これらはバイナリファイルであり、人間が解釈することは意図されていません。
デジタル署名ファイルは .SF ファイルと同じファイル名を持ちますが、異なる拡張子を持っています。拡張子はデジタル署名の型によって変化します。
.RSA (PKCS7 signature, MD5 + RSA)
.DSA (PKCS7 signature, DSA)
.PGP (Pretty Good Privacy Signature)
外部署名データをサポートしないこれらの形式については、ファイルは .SF ファイルの署名済みコピーからなります。あるデータは重複する可能性があるため、ベリファイアは 2 つのファイルを比較する必要があります。
外部データをサポートする形式は、.SF ファイルを参照するか、暗黙的な参照によって計算を実行します。
各 .SF ファイルは複数のデジタル署名を持つ可能性がありますが、これらの署名は同じ正当なエンティティによって生成される必要があります。
ファイル名の拡張子には、1 〜 3 文字の英数字を使うことができます。認識されない拡張子は無視されます。
マニフェストおよび署名ファイルについて
ここでは、マニフェストおよび署名ファイルに適用されるその他の制約および規則について説明します。
- 解析する前に:
ファイルの最後の文字が EOF 文字 (コード 26) の場合、EOF は空白として扱われる。2つの新しい行が追加される (1 つは最後の行の後ろに新しい行を置かないエディタ用で、1 つは文法上そのあとに空白行を持たない最後のエントリを、特別扱いしないようにするためのものである)
- 行の長さ:
すべての行は UTF-8 エンコード形式では、72 バイト (文字でない) を超えられない。値によって初期の行がこれ以上長くなる場合、追加行に継続する必要がある (各々の行は単一の「空白」で始まる)
- エラー:
ファイルをこの仕様に従って解析できない場合、警告を出力すべきであり、またどの署名も信用されるべきではない
- 制限:
ヘッダ名は継続できないため、ヘッダ名の最大長は 70 バイトである (名前のあとにコロンと「空白」がなければならない)
NUL、CR、LF はヘッダ値には含まれず、NUL、CR、LF、「:」はヘッダ名に含まれない。
実装では、65535 バイト (文字ではない) のヘッダ値、およびファイルごとに 65535 個のヘッダをサポートする必要がある。これによってメモリが不足するかもしれないが、これらの値にハードコーディングの制限があってはならない
- 署名者:
単一の署名ファイルを共有するために、異なるエンティティが異なる署名アルゴリズムを使用することは技術的に可能である。これは標準に従わないことになり、余分な署名が無視される
- アルゴリズム:
この仕様はダイジェストアルゴリズムまたは署名アルゴリズムを要求するものではない。 ただし、少なくとも MD5 と SHA のうちの 1 つがサポートされていなければならない
JAR インデックス
概要
1.3 から、ネットワークアプリケーション、特にアプレットのクラスローダによるクラス検索処理を最適化するために、JarIndex が導入されています。アプレットのクラスローダの基本機能では、単純な線形検索アルゴリズムによって、内部検索パスの各要素が検索されます。内部検索パスは、「ARCHIVE」タグまたは「Class-Path」メイン属性から構築されます。クラスまたはリソースが検出されるまで、クラスローダによって検索パスの各要素がダウンロードされて開かれます。クラスローダによって、存在しないリソースの検索が行われた場合、アプリケーションまたはアプレットの jar ファイルがすべてダウンロードされることになります。この結果、大きなネットワークアプリケーションおよびアプレットの場合は、起動および応答が遅くなり、ネットワーク帯域幅が浪費される可能性があります。JarIndex 機構では、アプレットに定義されている jar ファイルのコンテンツがすべて収集され、アプレットのクラスパスにある最初の jar ファイルのインデックスファイルにこの情報が格納されます。最初の jar ファイルがダウンロードされると、アプレットクラスローダでは、収集されたコンテンツ情報を使って効率的に jar ファイルがダウンロードされます。
既存の jar ツールの機能も拡張されています。jar ファイルのリストが検査されてから、クラスおよびリソースが属している jar ファイルについてのディレクトリ情報が生成されます。このディレクトリ情報は、ルート jar ファイルの META-INF ディレクトリの INDEX.LIST という名前の、単純なテキストファイル内に格納されます。クラスローダによって、ルート jar ファイルがロードされ、INDEX.LIST ファイルが読み込まれます。次に、そのファイルを使って、ファイルとパッケージ名から jar ファイル名のリストへのマッピングを格納したハッシュテーブルが構築されます。クラスローダによってクラスまたはリソースが検索される場合、ハッシュテーブルを問い合わせて、適切な jar ファイルが検出されてから、必要に応じてダウンロードされます。
クラスローダによって、特定の jar ファイルで INDEX.LIST ファイルが検出されると、そのファイルにリストされた情報は常に信頼されます。クラスローダによって特定のクラスのマッピングが検出されたあとで、リンクをたどってもそのクラスが検出されなかった場合は、InvalidJarIndexException がスローされます。この例外が発生した場合は、アプリケーション開発者は、拡張機能に対して jar ツールを実行し直し、インデックスファイルに正しい情報を取得する必要があります。
大量の領域オーバーヘッドの発生をアプリケーションで回避し、メモリ内のハッシュテーブルを高速で構築するために、INDEX.LIST ファイルの容量はできる限り小さくなるように管理されます。クラスのパッケージ名が null でない場合は、マッピングはパッケージレベルで記録されます。通常は、1 つのパッケージが 1 つの jar ファイルにマッピングされます。 ある特定のパッケージが 1 つ以上の jar ファイルにわたる場合は、このパッケージは jar ファイルのリストにマップされます。リソースファイルにディレクトリの接頭辞がある場合は、マッピングはディレクトリレベルで記録されます。 パッケージ名が null のクラスの場合およびルートディレクトリにリソースファイルが格納されている場合にだけ、マッピングがファイルレベルで記録されます。
インデックスファイルの仕様
INDEX.LIST ファイルには、1 つ以上のセクションが含まれ、それぞれ 1 行の空白行で区切られています。 セクションごとに 1 つの jar ファイルのコンテンツが定義されています。各セクションでは、jar ファイルのパス名を定義するヘッダのあとに、パッケージまたはファイル名が各行に定義されたリストが続きます。 すべての jar ファイルのパスは、ルート jar ファイルのコードベースを起点とする相対パスです。これらのパス名は、バンドル型拡張機能が現在の拡張機能機構によって解釈される方法と同じ方法で解決されます。
インデックスファイルのファイルまたはパッケージ名に、ASCII 以外の文字が使われているときは、UTF-8 エンコーディングが使われます。
仕様
index file : version-info blankline section*
version-info : JarIndex-Version:version-number
version-number : digit+{.digit+}*
section : body blankline
body : header name*
header : char+.jar newline
name : char+ newline
char : any valid Unicode character except NULL, CR and LF
blankline: newline newline
newline : CR LF | LF | CR (not followed by LF)
digit: {0-9}
INDEX.LIST ファイルは、jar -i. を実行することによって生成されます。詳細については jar のマニュアルページを参照してください。
下位互換性
新しいクラスのロード方式は、現在の拡張機能機構を基にして開発されたアプリケーションと完全な下位互換性があります。 クラスローダによって最初の jar ファイルがロードされ、META-INF ディレクトリ内で INDEX.LIST ファイルが検出されたときは、インデックスハッシュテーブルが構築され、その拡張機能に対して新しいロード方式が使われます。INDEX.LIST ファイルが検出されなかったときは、クラスローダでは元の線形検索アルゴリズムが使われます。
サービスプロバイダ
概要
META-INF/services ディレクトリ内のファイルは、サービスプロバイダの構成ファイルです。サービスとは、よく使われるインタフェースとクラス (通常は abstract) のセットのことです。サービスプロバイダとは、サービスの特定の実装のことです。通常、プロバイダのクラスによって、サービス自体に定義されているクラスのインタフェースとサブクラスが実装されます。サービスプロバイダを Java プラットフォームの実装にインストールするときは、拡張機能の形式、つまり、拡張機能の通常のディレクトリに配置される jar ファイルの形式で行われます。プロバイダを利用可能にするには、アプレットまたはアプリケーションのクラスパスに追加するか、プラットフォーム固有の方法を使います。
サービスは、abstract クラスによって表現されます。特定のサービスのプロバイダは、サービスのクラスを継承したいくつかの具象クラスで構成されています。サービスのクラスには、プロバイダ固有のデータおよびコードが含まれます。通常、プロバイダクラスには、プロバイダ自体がすべて含まれることはありません。要求時に実際のプロバイダを作成できるコードと、プロバイダが特定の要求を満たすことができるかどうかを識別するために必要な情報で構成されるプロキシになっています。プロバイダクラスの内容は、個別のサービスに大きく依存します。1 つのクラスまたはインタフェースでプロバイダクラスを統合することはできません。このため、このようなクラスは定義されていません。 プロバイダクラスには、ルックアップ中にインスタンスを生成できるように、引数を取らないコンストラクタが必要です。
プロバイダ構成ファイル
サービスプロバイダは、リソースディレクトリ META-INF/services にプロバイダ構成ファイルを配置することによって識別されます。このファイルの名前は、完全指定された abstract サービスクラス名で構成する必要があります。このファイルには、改行文字で区切られた、一意の具象プロバイダクラス名のリストを含める必要があります。空白、タブ文字、および空白行は無視されます。コメント文字は「#」(0x23) です。各行では、最初のコメント文字以降の文字はすべて無視されます。このファイルは、UTF-8 方式で符号化する必要があります。
例
java.io.spi.CharCodec という名前のサービスクラスを想定します。このクラスには、次の 2 つの abstract メソッドがあります。
public abstract CharEncoder getEncoder(String encodingName);
public abstract CharDecoder getDecoder(String encodingName);
これらのメソッドは、渡されたエンコーディングを変換できない場合、適切なオブジェクトまたは null を返します。標準の CharCodec プロバイダでは、複数のエンコーディングがサポートされています。
sun.io.StandardCodec が CharCodec サービスのプロバイダの場合は、jar ファイルに META-INF/services/java.io.spi.CharCodec ファイルが含まれます。このファイルには、次の行が含まれます。
sun.io.StandardCodec # Standard codecs for the platform
特定のエンコーディング名のエンコーダを検索するには、内部の I/O コードによって次のような処理が行われます。
CharEncoder getEncoder(String encodingName) {
Iterator ps = Service.providers(CharCodec.class);
while (ps.hasNext()) {
CharCodec cc = (CharCodec)ps.next();
CharEncoder ce = cc.getEncoder(encodingName);
if (ce != null)
return ce;
}
return null;
}
プロバイダのルックアップ機構は、常に呼び出し側のセキュリティコンテキストで実行されます。信頼できるシステムコードでは、通常、このクラスのメソッドは特権付きのセキュリティコンテキストから呼び出す必要があります。
API の詳細
パッケージ java.util.jar
関連項目
パッケージ java.security
パッケージ java.util.zip