JARファイルの仕様

目次

はじめに

JARファイルは普及しているZIPファイル形式に基づくファイル形式で、多数のファイルを1つにまとめるために使用されます。JAR ファイルは、基本的にはオプションのMETA-INFディレクトリを格納するZIPファイルです。JARファイルは、コマンド行jarツールか、Javaプラットフォームで java.util.jar APIを使用して作成できます。JARファイルの名前には制約がないため、各プラットフォームで許可されているファイル名を使うことができます。

多くの場合、JARファイルは、単純なJavaのクラス・ファイルまたはリソースのアーカイブではありません。これらは、アプリケーションおよび拡張機能の構築ブロックとして使用されます。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ファイルに格納されているパッケージまたはファイルの様々な属性を定義します。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種類の属性は、次のように定義されます。
 

メイン属性

メイン属性は、マニフェストのメイン・セクションに指定されている属性です。メイン属性は、次のグループに分類されます。

エントリ別属性

エントリ別属性は、そのマニフェスト・エントリが関連付けられている個別のJARファイル・エントリにだけ適用されます。メイン・セクションに同じ属性がある場合は、メイン属性の値はエントリ別属性の値によってオーバーライドされます。たとえば、JARファイルa.jarには、次のコンテンツがマニフェストに定義されています。
Manifest-Version: 1.0
Created-By: 1.2 (Sun Microsystems Inc.)
Sealed: true
Name: foo/bar/
Sealed: false

この場合、foo.barパッケージを除き、a.jar内にアーカイブされているパッケージがすべてシールされます。

エントリ別属性は、次のグループに分類されます。

署名付きJARファイル

概要

JARファイルに署名するには、コマンド行jarsignerツールを使うか、java.security APIを直接使います。JARファイルをjarsignerツールで署名した場合は、META-INFディレクトリ内の署名に関係しないファイルを含め、すべてのファイル・エントリが署名されます。署名に関係するファイルは次のとおりです。 署名に関係しないファイルがMETA-INFサブディレクトリ内にあっても、それらのファイルは署名に関係するファイルとは見なされません。上記のファイル名と大文字と小文字の区別が異なるファイル名は予約済みで、それらのファイルは署名されません。

JARファイルのサブセットを署名するには、java.security APIを使用します。署名されたJARファイルは、ファイルのマニフェストが更新されていることとMETA-INFディレクトリに署名ファイルと署名ブロック・ファイルが追加されていることを除けば、元のJARファイルとまったく同じです。jarsignerを使用しない場合、署名プログラムは、署名ファイルと署名ブロック・ファイルの両方を構築する必要があります。

署名付きJARファイル内で署名されたすべてのファイル・エントリについて、そのエントリがすでにマニフェスト内に存在していないかぎり、個別のマニフェスト・エントリが作成されます。各マニフェスト・エントリには、1つまたは複数のダイジェスト属性とオプションのMagic属性がリストされます。

署名ファイル

各署名者は、拡張子が.SFの署名ファイルによって表されます。このファイルの大部分は、マニフェスト・ファイルと同じです。このファイルは、署名者から提供された情報を含むメイン・セクションで構成されますが、この情報は特定のjarファイル・エントリに固有のものではありません。メイン・セクションには、Signature-VersionおよびCreated-By属性(「メイン属性」を参照)に加えて、次のセキュリティ属性を含めることができます。 メイン・セクションの後には、個々のエントリのリストが続きます。それらのエントリの名前も、マニフェスト・ファイル内に存在する必要があります。それぞれの個別エントリには、少なくともマニフェスト・ファイル内の対応するエントリのダイジェストが含まれている必要があります。

マニフェスト・ファイルに登場するが署名ファイルには登場しないパスまたはURLは、計算に使用されません。

署名の検証

JARファイルの検証が成功するのは、署名が有効であり、かつ署名の生成以後にJARファイル内のどのファイルも変更されていない場合です。JARファイルの検証は、次の手順で行われます。
  1. マニフェストがはじめて解析されるときに、署名を署名ファイルに対して検証します。効率化のために、この検証結果を記録しておくことができます。この検証では、実際のアーカイブ・ファイルでなく、署名そのものだけが検証されます。

  2. 署名ファイルに1つのx-Digest-Manifest属性が存在する場合は、マニフェスト全体から計算したダイジェストに照らして値を検証します。署名ファイルに複数のx-Digest-Manifest属性が存在する場合は、そのうち少なくとも1つが計算したダイジェスト値と一致することを検証します。

  3. 署名ファイルにx-Digest-Manifest属性が存在しないか、前の手順で計算したダイジェスト値がいずれも一致しない場合は、効率的に劣る方法で検証が行われます。

    1. 署名ファイルに1つのx-Digest-Manifest-Main-Attributesエントリが存在する場合は、マニフェスト・ファイル内のメイン属性から計算したダイジェストに照らして値を検証します。この計算に失敗すると、JARファイルの検証が失敗します。この判断は、効率化のために記録しておくことができます。署名ファイルにx-Digest-Manifest-Main-Attributesエントリが存在しなくても、JARファイルの検証に影響はなく、マニフェストのメイン属性が検証されないだけです。

    2. 署名ファイルの各ソース・ファイル情報セクション内の値を、マニフェスト・ファイルの対応するエントリから計算したダイジェスト値に照らして検証します。いずれのダイジェスト値も一致しない場合、JARファイルの検証が失敗します。

    x-Digest-Manifest属性に格納されたマニフェスト・ファイルのダイジェスト値が現在のマニフェスト・ファイルのダイジェスト値と一致しない場合は、署名(および署名ファイル)の生成後に(jarツールを使用して) JARファイルに1つ以上のファイルが追加された可能性があります。jarツールを使用してファイルを追加した場合、マニフェスト・ファイルは(新しいファイル用のセクションが追加されて)変更されますが、署名ファイルは変更されません。この場合、署名ファイルのヘッダー以外のセクションに格納されたダイジェスト値が、マニフェスト・ファイル内の対応するセクションのダイジェスト値と一致するときは、署名の生成時にJARファイル内に存在していたファイルのうち、どのファイルも変更されていないことになり、検証は成功したものとして扱われます。

  4. マニフェスト内のエントリごとに、「Name:」属性から参照される実際のデータ(相対ファイル・パスまたはURL)から計算されたダイジェストに照らして、マニフェスト・ファイル内のダイジェスト値を検証します。いずれのダイジェスト値も一致しない場合、JARファイルの検証が失敗します。

マニフェスト・ファイルの例:

Manifest-Version: 1.0
Created-By: 1.7.0 (Sun Microsystems 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ファイルとファイル名は同じですが、拡張子が異なります。拡張子はデジタル署名のタイプによって変化します。

上に示されていない署名アルゴリズム用のデジタル署名ファイルは、META-INFディレクトリに置き、「SIG-」という接頭辞を付ける必要があります。対応する署名ファイル(.SFファイル)にも同じ接頭辞を付けなければなりません。

外部署名データをサポートしない形式については、ファイルは.SFファイルの署名されたコピーで構成されることになります。したがって、一部のデータが重複する可能性があるため、ベリファイアは2つのファイルを比較する必要があります。

外部データをサポートする形式は、.SFファイルを参照するか、暗黙的な参照によって計算を実行します。

.SFファイルは複数のデジタル署名を持つ可能性がありますが、これらの署名は同じ正当なエンティティによって生成される必要があります。

ファイル名の拡張子には、1 - 3文字の英数字を使うことができます。認識されない拡張子は無視されます。

マニフェストおよび署名ファイルについて

ここでは、マニフェストおよび署名ファイルに適用されるその他の制約および規則について説明します。

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ファイルにマッピングされますが、パッケージが複数のjarファイルにわたる場合には、このパッケージのマップされた値はjarファイルのリストになります。リソース・ファイルにディレクトリの接頭辞がある場合は、マッピングはディレクトリ・レベルでも記録されます。パッケージ名がnullのクラスの場合およびルート・ディレクトリにリソース・ファイルが格納されている場合にのみ、マッピングが個別のファイル・レベルで記録されます。

インデックス・ファイルの仕様

INDEX.LISTファイルには、1つ以上のセクションが含まれ、それぞれ1行の空白行で区切られています。セクションごとに1つのjarファイルのコンテンツが定義されています。各セクションでは、jarファイルのパス名を定義するヘッダーの後に、パッケージ名またはファイル名のリストが1行ずつ続きます。すべての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 andLF
    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ファイルが検出されたときは、インデックス・ハッシュ表が構築され、その拡張機能に対して新しいロード方式が使われます。それ以外の場合、クラス・ローダーでは元の線形検索アルゴリズムが使われます。

サービス・プロバイダ

概要

META-INF/servicesディレクトリ内のファイルは、サービス・プロバイダの構成ファイルです。「サービス」とは、既知のインタフェースおよびクラス(通常はabstractクラス)のセットです。「サービス・プロバイダ」とは、特定のサービスの実装です。通常、プロバイダのクラスによって、サービス自体に定義されているクラスのインタフェースとサブクラスが実装されます。サービス・プロバイダをJavaプラットフォームの実装にインストールするときは、拡張機能の形式、つまり、拡張機能の通常のディレクトリに配置されるjarファイルの形式で行われます。プロバイダを利用可能にするには、アプレットまたはアプリケーションのクラス・パスに追加するか、プラットフォーム固有の方法を使います。

サービスは、抽象クラスによって表現されます。サービスのプロバイダには、このプロバイダに固有のデータおよびコードを使用してこのサービス・クラスを拡張する1つ以上の具象クラスが含まれています。通常、このプロバイダ・クラスは、プロバイダ全体そのものではなく、要求時に実際のプロバイダを作成できるコードと、プロバイダが特定の要求を満たすことができるかどうかを識別するために必要な情報で構成されるプロキシになります。プロバイダ・クラスの詳細は、個別のサービスにより大きく異なります。1つのクラスまたはインタフェースでプロバイダ・クラスを統合することはできないため、このようなクラスは定義されていません。プロバイダ・クラスには、参照中にインスタンス化できるように、ゼロ引数のコンストラクタが必要です。

プロバイダ構成ファイル

サービス・プロバイダは、リソース・ディレクトリMETA-INF/servicesにプロバイダ構成ファイルを配置することによって識別されます。このファイルの名前は、完全指定されたabstractサービス・クラス名で構成する必要があります。このファイルには、改行文字で区切られた、一意の具象プロバイダ・クラス名のリストを含める必要があります。空白文字とタブ文字、および空白行は無視されます。コメント文字は「#」(0x23)で、行の最初のコメント文字に続く文字はすべて無視されます。ファイルはUTF-8で符号化されている必要があります。

java.io.spi.CharCodecという名前のサービス・クラスを想定します。このクラスには、次の2つのabstractメソッドがあります。

これらのメソッドは、渡されたエンコーディングを変換できない場合、適切なオブジェクトまたは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;
   }

プロバイダのルックアップ・メカニズムは、常に呼出し側のセキュリティ・コンテキストで実行されます。信頼できるシステム・コードでは、通常、このクラスのメソッドは特権付きのセキュリティ・コンテキストから呼び出す必要があります。

Class-Path属性

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

アプリケーション(より一般的には、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は、アプリケーションまたはライブラリが含まれているファイルのロード元であるコード・ベースと突き合わせる形で解決されます。解決された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ファイルが必要になったときまで開かれません。

パッケージのシーリング

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ファイルが元になるパッケージで定義されているクラスに制限されるため、パッケージのシールはセキュリティの上でも重要です。

また、名前のないパッケージはシールできないので、シールすべきクラスはその独自のパッケージ内に置く必要があります。

APIの詳細

パッケージjava.util.jar

関連項目

パッケージjava.security

パッケージjava.util.zip


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