入門
JARファイルは普及しているZIPファイル形式に基づくファイル形式で、多数のファイルを1つにまとめるために使用されます。 JAR ファイルは、基本的にはオプションのMETA-INFディレクトリを格納するZIPファイルです。 JARファイルは、コマンドラインJARツールまたはJavaプラットフォームのjava.util.jar
APIを使用して作成できます。 JARファイルの名前には制約がないため、各プラットフォームで許可されているファイル名を使うことができます。
モジュラJARファイル
モジュラJARファイルは、最上位ディレクトリの(またはルート)ディレクトリにモジュール記述子module-info.class
を持つJARファイルです。 モジュール記述子は、モジュール宣言のバイナリ形式です。 (「マルチ・リリースJARファイル」の節では、モジュラJARファイルの定義をさらに詳しく説明しています。)
クラスパスではなくモジュール・パスにデプロイされたモジュラJARファイルは、explicitモジュールです。 依存関係とサービス・プロバイダは、モジュール記述子で宣言されます。 モジュラJARファイルがクラスパスにデプロイされている場合は、非モジュラJARファイルと同様に動作します。
モジュール・パスにデプロイされた非モジュラJARファイルは「自動モジュール」です。 JARファイルのメイン属性がAutomatic-Module-Name
(「メイン属性」を参照してください)の場合、属性値はモジュール名です。そうでない場合、モジュール名はModuleFinder.of(Path...)
で指定されたJARファイルの名前から導出されます。
マルチ・リリースJARファイル
マルチ・リリースJARファイルを使用すると、単一のJARファイルで複数のメジャー・バージョンのJavaプラットフォーム・リリースをサポートできます。 たとえば、マルチ・リリースJARファイルは、Java 8およびJava 9主要プラットフォーム・リリースの両方に依存することができます。いくつかのクラス・ファイルはJava 8のAPIに依存し、その他のクラス・ファイルはJava 9のAPIに依存します。 これにより、ライブラリとフレームワークの開発者は、すべてのユーザーがそのメジャー・バージョンに移行するという要件から、Javaプラットフォーム・リリースの特定のメジャー・バージョンでAPIの使用を切り離すことができます。 ライブラリとフレームワークの開発者は、古い機能をサポートしながら、徐々に新しいJava機能に移行してサポートすることができます。
マルチ・リリースJARファイルは、main属性で識別されます:
Multi-Release: true
「JARマニフェスト」のメイン・セクションで宣言されています。
Javaプラットフォーム・リリースの主要バージョン(9以上)に依存するクラスおよびリソース・ファイルは、最上位の(またはルート)ディレクトリの代わりに「バージョン管理されたディレクトリ」の下に置かれます。 バージョン管理されたディレクトリは「META-INFディレクトリ」の下にあり、次の形式です:
META-INF/versions/N
NはJavaプラットフォーム・リリースのメジャー・バージョン番号の文字列表現です。 具体的には、N
は仕様に準拠している必要があります:
N: | {1-9} {0-9} * |
---|
N
の値が9
より小さいバージョン化されたディレクトリは、上記の仕様に準拠しないN
の文字列表現と同様に無視されます。
マルチ・リリースJARのバージョンN
のversionedディレクトリ下のクラス・ファイルは、Javaプラットフォーム・リリースのメジャー・バージョンであるN
に関連付けられたクラス・ファイル・バージョン以下のクラス・ファイル・バージョンを持つ必要があります。 クラス・ファイルのクラスがパブリックまたは保護されている場合、そのクラスは最上位ディレクトリの下にクラス・ファイルが存在する完全修飾名とアクセス修飾子のクラスを「主宰」する必要があります。 論理拡張によって、バージョンがN
より小さいバージョン管理されたディレクトリの下に、クラス・ファイルのクラス(存在する場合)に適用されます。
マルチ・リリースJARファイルがJavaプラットフォーム・リリース・ランタイムのメジャー・バージョンN
のクラスパスまたはモジュール・パス(自動モジュールまたは明示的な「マルチ・リリース・モジュール」として)にデプロイされている場合、そのJARファイルからクラスをロードするクラス・ローダーは、最初にN
番目のバージョン・ディレクトリの下にあるクラス・ファイルを検索します9
の下位メジャー・バージョン境界まで、そして最終的に最上位ディレクトリの下に、降順(存在する場合)で以前にバージョン管理されたディレクトリを作成します。
マルチ・リリースのJARファイルでクラスによってエクスポートされたパブリックAPIは、バージョン間で同じでなければならないため、バージョン管理されたディレクトリの下にあるクラス・ファイルのバージョン管理されたpublicクラスまたはprotectedクラスは、レベルのディレクトリ。 jar
ツールなどのツールは、広範な検証を実行する必要はなく、検証を実行するためにJavaランタイムは必要ないため、広範なAPI検証チェックを実行するのは困難でコストがかかります。 この仕様の将来のリリースでは、慎重な進化をサポートするために全く同じAPI制約が緩和される可能性があります。
META-INF
ディレクトリの下のリソースは、バージョン(サービス構成など)にすることはできません。
マルチ・リリースJARファイルに署名することができます。
マルチ・リリースJARファイルは、Javaランタイムのブート・クラス・ローダーでサポートされていません。 マルチ・リリースJARファイルがブート・クラス・パス(-Xbootclasspath/a
オプション付き)に追加された場合、JARは通常のJARファイルであるかのように扱われます。
マルチ・リリースJARファイル
マルチ・リリースJARファイルは、モジュール記述子module-info.class
を最上位ディレクトリ(modular JARファイルの場合)に持つ、またはバージョン管理されたディレクトリに直接格納するマルチ・リリースJARファイルです。
エクスポートされていないパッケージ(モジュール記述子でエクスポートされたものとして宣言されていないもの)のパブリック・クラスまたは保護されたクラスは、トップレベルのディレクトリの下にクラス・ファイルが存在する同じ完全修飾名とアクセス修飾子のクラスを管理する必要はありません。
モジュール記述子は、一般に、他のクラスやリソース・ファイルとは異なる扱いを受けません。 モジュール記述子は、バージョン管理された領域の下に存在するが、最上位のディレクトリの下には存在しません。 これにより、たとえば、Java 8のバージョン付きクラスのみが最上位ディレクトリの下に存在することができます。一方、Java 9のバージョン付きクラス(おそらく、モジュール記述子)は、バージョン化された9
ディレクトリの下に存在することができます。
以下の2つの例外を除いて、よりバージョンの低いモジュール記述子を管理するバージョン管理されたモジュール記述子、または最上位レベルのM
は、M
と同一でなければなりません:
- 主要バージョン付き記述子は、
java.*
およびjdk.*
モジュールの異なる非transitive
requires
句を持つことができます; そして java.*
およびjdk.*
モジュールの外部で定義されたサービス・タイプであっても、主要なバージョン付き記述子は異なるuses
句を持つことができます。
jar
ツールなどのツールは、バージョン管理されたモジュール記述子の検証を実行する必要がありますが、Javaランタイムは検証を実行する必要はありません。
META-INFディレクトリ
META-INFディレクトリにある次のファイルやディレクトリは、アプリケーション、クラス・ローダーおよびサービスを構成するために、Java Platformで認識および解釈されます:
MANIFEST.MF
パッケージ関連のデータを定義するために使用されるマニフェスト・ファイル。
INDEX.LIST
このファイルは、jarツールの新しい"-i"
"オプションによって生成されます。このオプションには、アプリケーションで定義されたパッケージのロケーション情報が含まれています。 JarIndex実装に組み込まれており、クラスのロード処理を速くするためにクラス・ローダーによって使用されます。
x.SF
JARファイルの署名ファイルです。 「x」は、ベース・ファイル名を表します。
x.DSA
、x.RSA
またはx.EC
同じベース・ファイル名を持つ署名ファイルに関連付けられた署名ブロック・ファイル。 このファイルは、対応するシグネチャ・ファイルのデジタル・シグネチャをPKCS #7構造体に格納します。
services/
このディレクトリには、クラスパスにデプロイされたJARファイルのすべてのサービス・プロバイダ構成ファイル、またはモジュール・パスに自動モジュールとしてデプロイされたJARファイルが格納されます。 詳細は、「サービス・プロバイダの開発」の仕様を参照してください。
versions/
このディレクトリには、multi-release JARファイルのバージョン管理されたクラスとリソース・ファイルの下に含まれています。
名前-値ペアおよびセクション
各構成ファイルの内容を詳細に設定する前に、形式の規則をいくつか定義する必要があります。 ほとんどの場合、マニフェスト・ファイルまたは署名ファイルに含まれる情報は、RFC822の規定に従い、いわゆる「名前: 値」ペアとして表現されます。 これらのペアは、ヘッダーまたは属性とも呼ばれます。
名前-値ペアのグループを「セクション」と呼びます。 セクションはほかのセクションと空白行で分けられます。
バイナリ・データは、どの形式であれbase64で表されます。 行の長さが72バイトを超えるようなバイナリ・データについては継続が必要です。 バイナリ・データの例はダイジェストおよび署名です。
実装によっては、65535バイトまでのヘッダー値がサポートされます。
このドキュメントの仕様には同一の文法が使われており、終端記号は固定幅のフォントで示され、終端以外の記号はイタリック書体で示されています。
仕様部:
section: | *header +newline |
---|---|
nonempty-section: | +header +newline |
newline: | CR LF | LF | CR (LF に続かない) |
ヘッダー: | name : value |
name: | alphanum *headerchar |
value: | SPACE *otherchar newline *continuation |
continuation: | SPACE *otherchar newline |
alphanum: | { A-Z } | { a-z } | { 0-9 } |
headerchar: | alphanum | - | _ |
otherchar: | NUL, CR およびLF を除くUTF-8文字 |
- ノート: ストレート電子メールで送信されたファイルのリングを防ぐため、ヘッダーは4文字の"From"で始まりません。
上の仕様で定義されている終端以外の記号は、以降の仕様で使われています。
JARマニフェスト
概要
JARファイル・マニフェストは、メイン・セクションと各JARファイル・エントリの複数の個別セクションで構成され、それぞれ改行文字で区切られています。 メイン・セクションおよび個別セクションは、すでに説明したセクションの構文に準拠しています。 各セクションには、固有の制約と規則があります。
メイン・セクションには、アプリケーションと同様に、JARファイル自体に関するセキュリティおよび構成情報が含まれています。 また、各マニフェスト・エントリに適用されるメイン属性も定義します。 このセクションには、"
Name
"と等しい名前を持つ属性はありません。 メイン・セクションは、空白行で終わります。個別のセクションでは、このJARファイルに格納されているパッケージまたはファイルの様々な属性を定義します。 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 (LF に続かない) |
数字: | {0-9} |
上の仕様では、メイン・セクションに指定した属性はメイン属性、個別セクションに指定した属性はエントリ別属性として参照されます。 属性によっては、メイン・セクションと個別セクションの両方で指定できます。この場合、そのエントリでは、メイン属性の値はエントリ別属性の値によってオーバーライドされます。 これら2種類の属性は、次のように定義されます。
主な属性
メイン属性は、マニフェストのメイン・セクションに指定されている属性です。 メイン属性は、次のグループに分類されます。
- 一般的なメイン属性
- Manifest-Version: マニフェスト・ファイルのバージョンを定義する。 値は、上記の仕様に定義されている正当なバージョン番号。
- Created-By: このマニフェスト・ファイルが生成されるJava実装のバージョンおよびベンダーを定義する。 この属性は、
jar
ツールによって生成される。 - Signature-Version: jarファイルの署名のバージョンを定義する。 値は、有効なversion-number文字列でなければならない。
- Class-Path: この属性の値は、このアプリケーションに必要なライブラリの相対URLを指定します。 URLは1つ以上の空白で区切る。 アプリケーション・クラス・ローダーは、この属性の値を使用して内部検索パスを構築します。 詳細については、「クラスパス属性」セクションを参照してください。
- Automatic-Module-Name: このJARファイルがモジュール・パス上の自動モジュールとしてデプロイされている場合は、モジュール名を定義します。 詳細については、
automatic modules
の仕様を参照してください。 - Multi-Release: この属性は、このJARファイルがmulti-release JARファイルかどうかを定義します。 値が"true"の場合、大文字小文字は無視され、JARファイルはJavaランタイムとツールでマルチ・リリースJARファイルとして処理されます。 それ以外の場合、値が"true"以外の場合、この属性は無視されます。
- スタンドアロン・アプリケーション用に定義された属性: この属性は、"
java -jar x.jar
"を実行してjavaランタイムで直接起動できる実行可能jarファイルにバンドルされているスタンドアロン・アプリケーションで使用されます。- Main-Class: この属性の値は、起動時に起動ツールによってロードされるメイン・アプリケーション・クラスのクラス名である。 この値には、クラス名に拡張子「
.class
」が付いていてはならない。 - Launcher-Agent-Class: この属性が存在する場合、その値は、アプリケーションのメイン・メソッドが呼び出される前に開始される「Javaエージェント」のクラス名です。 この属性は、Javaエージェントがアプリケーションと同じ実行可能JARファイルにパッケージ化されている場合に使用できます。 エージェント・クラスは、
java.lang.instrument
パッケージ・サマリーで指定された2つの形式のうちの1つにパブリック静的メソッド名agentmain
を定義します。 追加の属性(Can-Retransform-Classes
)を使用して、エージェントが必要とする機能を示すことができます。
- Main-Class: この属性の値は、起動時に起動ツールによってロードされるメイン・アプリケーション・クラスのクラス名である。 この値には、クラス名に拡張子「
- 「パッケージのバージョニングとリング」情報のために定義された属性: これらの属性の値は、JARファイル内のすべてのパッケージに適用されますが、エントリごとの属性によって上書きできます。
- Implementation-Title: 拡張機能の実装のタイトルを定義する文字列。
- Implementation-Version: 拡張機能の実装のバージョンを定義する文字列。
- Implementation-Vendor: 拡張機能の実装を管理するベンダーを定義する文字列。
- Specification-Title: 拡張機能の仕様のタイトルを定義する文字列。
- Specification-Version: 拡張機能の仕様のバージョンを定義する文字列。
- Specification-Vendor: 拡張機能の仕様を管理するベンダーを定義する文字列。
- Sealed: このJARファイルがシールされるかどうかを定義する。 値は「true」または「false」で、大文字と小文字は区別されない。 「true」に設定した場合は、JARファイル内のパッケージは、個別に定義しないかぎり、すべてデフォルトでシールされる。 「パッケージ・シーリング」セクションも参照してください。
エントリ別属性
エントリ別属性は、そのマニフェスト・エントリが関連付けられている個別のJARファイル・エントリにだけ適用されます。 メイン・セクションに同じ属性がある場合は、メイン属性の値はエントリ別属性の値によってオーバーライドされます。 たとえば、JARファイルa.jarには、次のコンテンツがマニフェストに定義されています。
Manifest-Version: 1.0
Created-By: 1.8 (Oracle Inc.)
Sealed: true
Name: foo/bar/
Sealed: false
この場合、foo.barパッケージを除き、a.jar内にアーカイブされているパッケージがすべてシールされます。
エントリ別属性は、次のグループに分類されます。
- ファイルのコンテンツに対して定義する属性:
- パッケージのバージョン管理およびシーリング情報に対して定義する属性: 前述の、拡張機能パッケージのバージョン管理およびシーリング情報を定義するメイン属性として定義されている属性セットと同じ。 エントリ別属性として使う場合は、メイン属性はオーバーライドされるが、マニフェスト・エントリにより指定された個別のファイルにのみ適用される。
- Beansオブジェクトに対して定義する属性:
- Java-Bean: 特定のjarファイル・エントリが、Java Beansオブジェクトかどうかを定義する。 値は「true」または「false」で、大文字と小文字は区別されない。
- 署名に対して定義する属性: 次の属性は、署名と検証のために使われる。 詳細は次のとおり。
- x-Digest-y: この属性の名前には、対応するjarファイル・エントリのダイジェスト値の計算に使われるダイジェスト・アルゴリズムの名前を指定する。 この属性の値には、実際のダイジェストの値が格納される。 接頭辞の「x」でアルゴリズム名を指定し、オプションの接尾辞「y」でダイジェスト値の検証基準の言語を指定する。
- Magic: これはオプションの属性で、マニフェスト・エントリで指定されたダイジェスト値をベリファイアが計算する方法を指定するために、アプリケーションで使われる。 値には、カンマで区切られたコンテキスト固有の文字列を指定する。 詳細は、以降の説明を参照。
署名付きJARファイル
概要
JARファイルに署名するには、コマンド行jarsignerツールを使うか、java.security
APIを直接使います。 JARファイルをjarsignerツールで署名した場合は、META-INF
ディレクトリ内の署名に関係しないファイルを含め、すべてのファイル・エントリが署名されます。 署名に関係するファイルは次のとおりです。
META-INF/MANIFEST.MF
META-INF/*.SF
META-INF/*.DSA
META-INF/*.RSA
META-INF/*.EC
META-INF/SIG-*
署名に関係しないファイルがMETA-INF
サブディレクトリ内にあっても、それらのファイルは署名に関係するファイルとは見なされません。 上記のファイル名と大文字と小文字の区別が異なるファイル名は予約済みで、それらのファイルは署名されません。
JARファイルのサブセットを署名するには、java.security
APIを使用します。 署名されたJARファイルは、ファイルのマニフェストが更新されていることとMETA-INF
ディレクトリに署名ファイルと署名ブロック・ファイルが追加されていることを除けば、元のJARファイルとまったく同じです。 jarsignerを使用しない場合、署名プログラムは、署名ファイルと署名ブロック・ファイルの両方を構築する必要があります。
署名付きJARファイル内で署名されたすべてのファイル・エントリについて、そのエントリがすでにマニフェスト内に存在していないかぎり、個別のマニフェスト・エントリが作成されます。 各マニフェスト・エントリには、1つまたは複数のダイジェスト属性とオプションのMagic属性がリストされます。
署名ファイル
各署名者は、拡張子が.SF
の署名ファイルによって表されます。 このファイルの大部分は、マニフェスト・ファイルと同じです。 このファイルは、署名者から提供された情報を含むメイン・セクションで構成されますが、この情報は特定のjarファイル・エントリに固有のものではありません。 メイン・セクションには、Signature-Version
およびCreated-By
属性(「メイン属性」を参照)に加えて、次のセキュリティ属性を含めることができます。
- x-Digest-Manifest-Main-Attributes (xは
java.security.MessageDigest
アルゴリズムの標準名)。この属性の値は、マニフェストのメイン属性のダイジェスト値になる。 - x-Digest-Manifest (xは
java.security.MessageDigest
アルゴリズムの標準名)。この属性の値は、マニフェスト全体のダイジェスト値になる。
メイン・セクションの後には、個々のエントリのリストが続きます。それらのエントリの名前も、マニフェスト・ファイル内に存在する必要があります。 それぞれの個別エントリには、少なくともマニフェスト・ファイル内の対応するエントリのダイジェストが含まれている必要があります。
マニフェスト・ファイルに登場するが署名ファイルには登場しないパスまたはURLは、計算に使用されません。
署名の検証
JARファイルの検証が成功するのは、署名が有効であり、かつ署名の生成以後にJARファイル内のどのファイルも変更されていない場合です。 JARファイルの検証は、次のステップで行われます。
マニフェストがはじめて解析されるときに、署名を署名ファイルに対して検証します。 効率化のために、この検証結果を記録しておくことができます。 この検証では、実際のアーカイブ・ファイルでなく、署名そのものだけが検証されます。
署名ファイルに1つの
x-Digest-Manifest
属性が存在する場合は、マニフェスト全体から計算したダイジェストに照らして値を検証します。 署名ファイルに複数のx-Digest-Manifest
属性が存在する場合は、そのうち少なくとも1つが計算したダイジェスト値と一致することを検証します。署名ファイルに
x-Digest-Manifest
属性が存在しないか、前のステップで計算したダイジェスト値がいずれも一致しない場合は、効率的に劣る方法で検証が行われます。署名ファイルに1つの
x-Digest-Manifest-Main-Attributes
エントリが存在する場合は、マニフェスト・ファイル内のメイン属性から計算したダイジェストに照らして値を検証します。 この計算に失敗すると、JARファイルの検証が失敗します。 この判断は、効率化のために記録しておくことができます。 署名ファイルにx-Digest-Manifest-Main-Attributes
エントリが存在しなくても、JARファイルの検証に影響はなく、マニフェストのメイン属性が検証されないだけです。署名ファイルの各ソース・ファイル情報セクション内の値を、マニフェスト・ファイルの対応するエントリから計算したダイジェスト値に照らして検証します。 いずれのダイジェスト値も一致しない場合、JARファイルの検証が失敗します。
x-Digest-Manifest
属性に格納されているマニフェスト・ファイルのダイジェスト値が、現在のマニフェスト・ファイルのダイジェスト値と等しくない場合、ファイルの署名後に新しく追加されたファイルのセクションが含まれる可能性があります。 たとえば、シグネチャ(シグネチャ・ファイル)の生成後に、1つ以上のファイルがJARファイル(jarツールの使用)に追加されたとします。 JARファイルが別のシグネチャ者によって再度シグネチャされた場合、マニフェスト・ファイルが(jarsignerツールを使用して、新規ファイルに対してセクションを追加)に変更され、新しいシグネチャ・ファイルが作成されますが、元のシグネチャ・ファイルは変更されません。 シグネチャの生成時にJARファイルに含まれていたファイルがその後変更されていない場合、元のシグネチャに対する検証は成功とみなされます。これは、シグネチャ・ファイルの非ヘッダー・セクションのダイジェスト値が、マニフェスト・ファイルの対応するセクションのダイジェスト値と等しい場合に該当します。マニフェスト内のエントリごとに、「Name:」属性から参照される実際のデータ(相対ファイル・パスまたはURL)から計算されたダイジェストに照らして、マニフェスト・ファイル内のダイジェスト値を検証します。 いずれのダイジェスト値も一致しない場合、JARファイルの検証が失敗します。
マニフェスト・ファイルの例:
Manifest-Version: 1.0
Created-By: 1.8.0 (Oracle Inc.)
Name: common/class1.class
SHA-256-Digest: (base64 representation of SHA-256 digest)
Name: common/class2.class
SHA1-Digest: (base64 representation of SHA1 digest)
SHA-256-Digest: (base64 representation of SHA-256 digest)
対応する署名ファイルは次のようになります。
Signature-Version: 1.0
SHA-256-Digest-Manifest: (base64 representation of SHA-256 digest)
SHA-256-Digest-Manifest-Main-Attributes: (base64 representation of SHA-256 digest)
Name: common/class1.class
SHA-256-Digest: (base64 representation of SHA-256 digest)
Name: common/class2.class
SHA-256-Digest: (base64 representation of SHA-256 digest)
Magic属性
特定のマニフェスト・エントリ上で署名を有効化するためにもう1つ必要なことは、そのエントリのマニフェスト・エントリ内のMagicキー・ペア値の値をベリファイアが理解することです。
Magic属性はオプションですが、パーサーがそのエントリの署名を検証する場合は、エントリのMagicキーの値を理解する必要があります。
Magic属性の値は、カンマで区切られたコンテキスト固有の文字列のセットです。 カンマの前後の空白は無視されます。 大文字小文字も無視されます。 Magic属性の正確な意味はアプリケーションによって異なります。 これらの属性は、マニフェスト・エントリに含まれるハッシュ値の計算方法を示し、そのため署名の正しい検証には欠くことのできないものです。 このキーワードは、動的または埋込みコンテンツ、多国語ドキュメント用の複数ハッシュなどに使用します。
次に、マニフェスト・ファイルでのMagic属性の使用例を2つ示します。
Name: http://www.example-scripts.com/index#script1
SHA-256-Digest: (base64 representation of SHA-256 hash)
Magic: JavaScript, Dynamic
Name: http://www.example-tourist.com/guide.html
SHA-256-Digest: (base64 representation of SHA-256 hash)
SHA-256-Digest-French: (base64 representation of SHA-256 hash)
SHA-256-Digest-German: (base64 representation of SHA-256 hash)
Magic: Multilingual
最初の例では、これらMagicの値はhttp問い合わせの結果がドキュメント自身ではなく、ドキュメントに埋め込まれたスクリプトであり、またそのスクリプトが動的に生成されるということを示します。 この2つの情報は、マニフェストのダイジェスト値と比較し、有効な署名と比較するハッシュ値の計算方法を示します。
第2の例では、Magic値は検索されたドキュメントの内容は特定の言語であるという合意を示し、検証のためのダイジェストの値は検索されたドキュメントを記述する言語に依存することを示します。
デジタル署名
デジタル署名とは、署名された.SF
署名ファイルです。 これらはバイナリ・ファイルであり、人間が解釈することは意図されていません。
デジタル署名ファイルは、.SFファイルとファイル名は同じですが、拡張子が異なります。 拡張機能は、署名者非公開キーのアルゴリズムによって異なります。
.RSA
(PKCS7シグネチャ(RSAまたはRSASSA-PSSキーの場合)).DSA
(PKCS7シグネチャ、DSAキー用).EC
(PKCS7シグネチャ(ECまたはEdDSAキーの場合))
上に示されていない署名アルゴリズム用のデジタル署名ファイルは、META-INF
ディレクトリに置き、「SIG-
」という接頭辞を付ける必要があります。 対応するシグネチャ・ファイル(.SF
ファイル)にも同じプレフィクスが必要です。
外部署名データをサポートしない形式については、ファイルは.SF
ファイルの署名されたコピーで構成されることになります。 したがって、一部のデータが重複する可能性があるため、ベリファイアは2つのファイルを比較する必要があります。
外部データをサポートする形式は、.SF
ファイルを参照するか、暗黙的な参照によって計算を実行します。
各.SF
ファイルは複数のデジタル署名を持つ可能性がありますが、これらの署名は同じ正当なエンティティによって生成される必要があります。
ファイル名の拡張子には、1 - 3文字の英数字を使うことができます。 認識されない拡張子は無視されます。
マニフェストおよび署名ファイルについてのノート
ここでは、マニフェストおよび署名ファイルに適用されるその他の制約および規則について説明します。
- 属性:
- 各セクションのすべてのケースで、理解できない属性は無視される。
- 属性名は大文字と小文字が区別されない。 しかし、マニフェストおよび署名ファイルを生成するプログラムはこの仕様で示されているとおりに大文字と小文字を使い分ける必要がある。
- 属性名はセクション内で繰り返してはならない。
- バージョン:
- Manifest-VersionおよびSignature-Versionは最初でなければならず、大文字と小文字の使分けを確実に守らなければならない(こうしてこれらをmagic文字列として簡単に認識できるようにする)。 それ以外は、メイン・セクション内の属性の順番は重要ではない。
- 順番付け:
- 各マニフェスト・エントリの順番は重要ではない。
- 各署名エントリの順番は、署名されるダイジェストがその順番になることを除けば重要ではない。
- 行の長さ:
- すべての行はUTF-8エンコード形式では、72バイト(文字でない)を超えられない。 値によって初期の行がこれ以上長くなる場合、追加行に継続する必要がある(それぞれの行は単一の「空白」で始まる)。
- エラー:
- ファイルをこの仕様に従って分解できない場合、警告を出力すべきであり、またどの署名も信用されるべきではない。
- 制限:
- ヘッダー名は継続できないため、ヘッダー名の最大長は70バイトである(名前のあとにコロンと「空白」がなければならない)。
- NUL、CR、LFをヘッダー値には含められず、NUL、CR、LF、「:」はヘッダー名に含められません。
- 実装では、65535バイト(文字ではない)のヘッダー値、およびファイルごとに65535個のヘッダーをサポートする必要がある。 これによってメモリーが不足する可能性があるが、これらの値にハード・コーディングの制限があってはならない。
- 署名者:
- 単一の署名ファイルを共有するために、異なるエンティティが異なる署名アルゴリズムを使用することは技術的に可能である。 これは標準に従わないことになり、余分な署名が無視される。
- アルゴリズム:
- この仕様はダイジェスト・アルゴリズムまたは署名アルゴリズムを要求するものではない。 ただし、SHA-256およびSHA1ダイジェスト・アルゴリズムの少なくとも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
ファイルが検出されると、そのファイルにリストされた情報は常に信頼されます。 特定のクラスに対してマッピングが見つかったが、リンクをたどってクラス・ローダーがそれを見つけられなかった場合は、不特定のErrorまたはRuntimeExceptionがスローされます。 この例外が発生した場合は、アプリケーション開発者は、拡張機能に対してjar
ツールを実行し直し、インデックス・ファイルに正しい情報を取得する必要があります。
大量の領域オーバーヘッドの発生をアプリケーションで回避し、インメモリー・ハッシュ表を高速で構築するために、INDEX.LISTファイルの容量はできるかぎり小さくなるように管理されます。 クラスのパッケージ名がnullでない場合は、マッピングはパッケージ・レベルで記録されます。 通常は、1つのパッケージ名が1つのjarファイルにマッピングされますが、パッケージが複数のjarファイルにわたる場合には、このパッケージのマップされた値はjarファイルのリストになります。 リソース・ファイルにディレクトリの接頭辞がある場合は、マッピングはディレクトリ・レベルでも記録されます。 パッケージ名がnullのクラスの場合およびルート・ディレクトリにリソース・ファイルが格納されている場合にのみ、マッピングが個別のファイル・レベルで記録されます。
インデックス・ファイルの仕様
INDEX.LIST
ファイルには、1つ以上のセクションが含まれ、それぞれ1行の空白行で区切られています。 セクションごとに1つのjarファイルのコンテンツが定義されています。各セクションでは、jarファイルのパス名を定義するヘッダーの後に、パッケージ名またはファイル名のリストが1行ずつ続きます。 すべてのjarファイルのパスは、ルートjarファイルのコード・ベースを起点とする相対パスです。 これらのパス名は、バンドル型拡張機能が現在の拡張機能メカニズムによって解釈される方法と同じ方法で解決されます。
インデックス・ファイルのファイル名またはパッケージ名に、ASCII以外の文字が使われているときは、UTF-8エンコーディングが使われます。
Specification
索引ファイル: | version-info blankline section* |
---|---|
version-info: | JarIndex-Version: version-number |
version-number: | digit+{.digit+}* |
section: | body blankline |
body: | header name* |
ヘッダー: | char+.jar newline |
name: | char+ newline |
char: | NULL, CR およびLF を除く有効なUnicode文字 |
blankcline: | newline newline |
newline: | CR LF | LF | CR (LF に続かない) |
数字: | {0-9 } |
INDEX.LIST
ファイルは、jar -i.
を実行して生成されます 詳細は、jarのマニュアル・ページを参照してください。
下位互換性
新しいクラスのロード方式は、現在の拡張機能メカニズムを基にして開発されたアプリケーションと完全な下位互換性があります。 クラス・ローダーによって最初のjarファイルがロードされ、META-INF
ディレクトリ内でINDEX.LIST
ファイルが検出されたときは、インデックス・ハッシュ表が構築され、その拡張機能に対して新しいロード方式が使われます。 それ以外の場合、クラス・ローダーでは元の線形検索アルゴリズムが使われます。
Class-Path属性
アプリケーションのマニフェストでは、必要な他のライブラリのJARファイルとディレクトリを参照する1つ以上の相対URLを指定できます。 これらの相対Urlは、包含するアプリケーションが(「コンテキストJAR」)からロードされたコード・ベースを基準として処理されます。
アプリケーション(またはより一般的には、JARファイル)は、マニフェスト属性Class-Path
を使用して、必要なライブラリの相対URLを指定します。 この属性は、ホストJava Virtual Machine上に見つからない場合、他のライブラリの実装を検索するためのURLをリストします。 この相対URLには、アプリケーションが必要とするライブラリまたはリソースが含まれるJARファイルとディレクトリを含めることができます。 「/」で終わらないURLは、JARファイルを参照しているものとみなされます。 たとえば、
Class-Path: servlet.jar infobus.jar acme/beans.jar images/
JARファイルのマニフェストで指定できるClass-Path
ヘッダーは1つだけです。
次の条件に該当する場合、Class-Path
エントリは有効です:
これを使用して
URL
を作成し、コンテキストJARのURLに対して解決できます。「絶対」ではなく相対的です。つまり、スキーム・コンポーネントが含まれていません。ただし、コンテキストJARがファイル・システムからロードされた場合は例外で、この場合
file
スキームは互換性上の理由で許可されます。このエントリによって表されるJARファイルまたはディレクトリのロケーションは、コンテキストJARの格納ディレクトリ内に含まれます。 "
../
"を使用して親ディレクトリに移動することはできません。ただし、コンテキストJARがファイル・システムからロードされた場合は例外です。
無効な入力は無視されます。 有効なエントリはコンテキストJARに対して解決されます。 解決されたURLが無効であるか、参照するリソースが見つからない場合、そのURLは無視されます。 重複したUrlは無視されます。
生成されるURLは、コンテキストJARのURLの直後にクラス・パスに挿入されます。 たとえば、次のようなクラス・パスが指定されているとします。
a.jar b.jar
b.jar
に次のClass-Path
マニフェスト属性が含まれている場合:
Class-Path: lib/x.jar a.jar
その後、このようなURLClassLoader
インスタンスの有効な検索パスは次のようになります:
a.jar b.jar lib/x.jar
もちろん、x.jar
に依存情報が含まれる場合は、依存ファイルはこれと同じ規則に従って追加されます。後に続くURLについても同様です。 実際の実装では、JARファイルの依存関係は先に処理されるのではなく、JARファイルが実際に必要になったときまで開かれません。
パッケージのシーリング
JARファイルとパッケージは、同一バージョン内で整合性が保たれるように、オプションでシール,することができます。
JARファイル内のパッケージをシールした場合、そのパッケージ内で定義されているすべてのクラスは、同一のJARファイルが元になっていなければなりません。 そうでない場合は、SecurityException
がスローされます。
JARファイルをシールした場合、そのJARファイルで定義されているすべてのパッケージは、特別に設定をオーバーライドしないかぎり、シールされます。
パッケージをシールするかどうかは、マニフェスト属性Sealed
で指定します。このマニフェスト属性は、true
かfalse
の値をとります。大文字小文字は区別されません。 たとえば、
Name: javax/servlet/internal/
Sealed: true
このように指定すると、javax.servlet.internal
がシールされ、このパッケージに含まれるすべてのクラスは同一のJARファイルからロードされなければなりません。
この属性が指定されていない場合は、パッケージのシール属性は、そのパッケージが含まれるJARファイルのシール属性と同じになります。
JARファイルをシールするかどうかは、上と同じマニフェスト・ヘッダーSealed
で指定します。このマニフェスト・ヘッダーも、同じくtrue
かfalse
の値をとります。 たとえば、
Sealed: true
このように指定すると、このアーカイブに含まれるすべてのパッケージは、マニフェスト・エントリの中でSealed
属性により明示的に設定をオーバーライドしないかぎり、シールされます。
この属性が指定されていない場合は、下位互換性を保つため、そのJARファイルはシールされていないものとみなされます。 このあと、システムはシール情報を見るため、パッケージのヘッダーのチェックを継続します。
パッケージをシールすると、パッケージ保護されたメンバーへのアクセスは、同一のJARファイルが元になるパッケージで定義されているクラスに制限されるため、パッケージのシールはセキュリティの上でも重要です。
名前のないパッケージはシール可能ではないため、シールするクラスはそれぞれのパッケージに配置する必要があります。
API詳細
パッケージjava.util.jar
関連項目
パッケージjava.security
パッケージjava.util.zip