java中的jar文件

官方英文介紹*******************************************************************************************

Introduction

JAR file is a file format based on the popular ZIP file format and is used for aggregating many files into one. A JAR file is essentially a zip file that contains an optional META-INF directory. A JAR file can be created by the command-line jar tool, or by using the java.util.jar API in the Java platform. There is no restriction on the name of a JAR file, it can be any legal file name on a particular platform.

Modular JAR files

A modular JAR file is a JAR file that has a module descriptor, module-info.class, in the top-level directory (or root) directory. The module descriptor is the binary form of a module declaration. (Note the section on multi-release JAR files further refines the definition of modular JAR files.)

A modular JAR file deployed on the module path, as opposed to the class path, is an explicit module. Dependences and service providers are declared in the module descriptor. If the modular JAR file is deployed on the class path then it behaves as if a non-modular JAR file.

A non-modular JAR file deployed on the module path is an automatic module. If the JAR file has a main attribute Automatic-Module-Name (see Main Attributes) then the attribute's value is the module name, otherwise the module name is derived from the name of the JAR file as specified in ModuleFinder.of(Path...).

Multi-release JAR files

A multi-release JAR file allows for a single JAR file to support multiple major versions of Java platform releases. For example, a multi-release JAR file can depend on both the Java 8 and Java 9 major platform releases, where some class files depend on APIs in Java 8 and other class files depend on APIs in Java 9. This enables library and framework developers to decouple the use of APIs in a specific major version of a Java platform release from the requirement that all their users migrate to that major version. Library and framework developers can gradually migrate to and support new Java features while still supporting the old features.

A multi-release JAR file is identified by the main attribute:

Multi-Release: true

declared in the main section of the JAR Manifest.

Classes and resource files dependent on a major version, 9 or greater, of a Java platform release may be located under a versioned directory instead of under the top-level (or root) directory. The versioned directory is located under the the META-INF directory and is of the form:

META-INF/versions/N

where N is the string representation of the major version number of a Java platform release. Specifically N must conform to the specification:

N: {1-9} {0-9}*

Any versioned directory whose value of N is less than 9 is ignored as is a string representation of N that does not conform to the above specification.

A class file under a versioned directory, of version N say, in a multi-release JAR must have a class file version less than or equal to the class file version associated with Nth major version of a Java platform release. If the class of the class file is public or protected then that class must preside over a class of the same fully qualified name and access modifier whose class file is present under the top-level directory. By logical extension this applies to a class of a class file, if present, under a versioned directory whose version is less than N.

If a multi-release JAR file is deployed on the class path or module path (as an automatic module or an explicit multi-release module) of major version N of a Java platform release runtime, then a class loader loading classes from that JAR file will first search for class files under the Nth versioned directory, then prior versioned directories in descending order (if present), down to a lower major version bound of 9, and finally under the top-level directory.

The public API exported by the classes in a multi-release JAR file must be exactly the same across versions, hence at a minimum why versioned public or protected classes for class files under a versioned directory must preside over classes for class files under the top-level directory. It is difficult and costly to perform extensive API verification checks as such tooling, such as the jar tool, is not required to perform extensive verification and a Java runtime is not required to perform any verification. A future release of this specification may relax the exact same API constraint to support careful evolution.

Resources under the META-INF directory cannot be versioned (such as for service configuration).

A multi-release JAR file can be signed.

Multi-release JAR files are not supported by the boot class loader of a Java runtime. If a multi-release JAR file is appended to the boot class path (with the -Xbootclasspath/a option) then the JAR is treated as if it is an ordinary JAR file.

Modular multi-release JAR files

A modular multi-release JAR file is a multi-release JAR file that has a module descriptor, module-info.class, in the top-level directory (as for a modular JAR file), or directly in a versioned directory.

A public or protected class in a non-exported package (that is not declared as exported in the module descriptor) need not preside over a class of the same fully qualified name and access modifier whose class file is present under the top-level directory.

A module descriptor is generally treated no differently to any other class or resource file. A module descriptor may be present under a versioned area but not present under the top-level directory. This ensures, for example, only Java 8 versioned classes can be present under the top-level directory while Java 9 versioned classes (including, or perhaps only, the module descriptor) can be present under the 9 versioned directory.

Any versioned module descriptor that presides over a lesser versioned module descriptor or that at the top-level, M say, must be identical to M, with two exceptions:

  1. the presiding versioned descriptor can have different non-transitive requires clauses of java.* and jdk.* modules; and
  2. the presiding versioned descriptor can have different uses clauses, even of service types defined outside of java.* and jdk.* modules.

Tooling, such as the jar tool, should perform such verification of versioned module descriptors but a Java runtime is not required to perform any verification.

The META-INF directory

The following files/directories in the META-INF directory are recognized and interpreted by the Java 2 Platform to configure applications, class loaders and services:

  • MANIFEST.MF

The manifest file that is used to define package related data.

  • INDEX.LIST

This file is generated by the new "-i" option of the jar tool, which contains location information for packages defined in an application. It is part of the JarIndex implementation and used by class loaders to speed up their class loading process.

  • x.SF

The signature file for the JAR file. 'x' stands for the base file name.

  • x.DSA

The signature block file associated with the signature file with the same base file name. This file stores the digital signature of the corresponding signature file.

  • services/

This directory stores all the service provider configuration files for JAR files deployed on the class path or JAR files deployed as automatic modules on the module path. See the specification of service provider development for more details.

  • versions/

This directory contains underneath it versioned class and resource files for a multi-release JAR file.

Name-Value pairs and Sections

Before we go to the details of the contents of the individual configuration files, some format convention needs to be defined. In most cases, information contained within the manifest file and signature files is represented as so-called "name: value" pairs inspired by the RFC822 standard. We also call these pairs headers or attributes.

Groups of name-value pairs are known as a "section". Sections are separated from other sections by empty lines.

Binary data of any form is represented as base64. Continuations are required for binary data which causes line length to exceed 72 bytes. Examples of binary data are digests and signatures.

Implementations shall support header values of up to 65535 bytes.

All the specifications in this document use the same grammar in which terminal symbols are shown in fixed width font and non-terminal symbols are shown in italic type face.

Specification:

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
  • Note: To prevent mangling of files sent via straight e-mail, no header will start with the four letters "From".

Non-terminal symbols defined in the above specification will be referenced in the following specifications.

JAR Manifest

Overview

A JAR file manifest consists of a main section followed by a list of sections for individual JAR file entries, each separated by a newline. Both the main section and individual sections follow the section syntax specified above. They each have their own specific restrictions and rules.

  • The main section contains security and configuration information about the JAR file itself, as well as the application. It also defines main attributes that apply to every individual manifest entry. No attribute in this section can have its name equal to "Name". This section is terminated by an empty line.

  • The individual sections define various attributes for packages or files contained in this JAR file. Not all files in the JAR file need to be listed in the manifest as entries, but all files which are to be signed must be listed. The manifest file itself must not be listed. Each section must start with an attribute with the name as "Name", and the value must be a relative path to the file, or an absolute URL referencing data outside the archive.

  • If there are multiple individual sections for the same file entry, the attributes in these sections are merged. If a certain attribute have different values in different sections, the last one is recognized.

  • Attributes which are not understood are ignored. Such attributes may include implementation specific information used by applications.

Manifest Specification:

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}

In the above specification, attributes that can appear in the main section are referred to as main attributes, whereas attributes that can appear in individual sections are referred to as per-entry attributes. Certain attributes can appear both in the main section and the individual sections, in which case the per-entry attribute value overrides the main attribute value for the specified entry. The two types of attributes are defined as follows.

Main Attributes

Main attributes are the attributes that are present in the main section of the manifest. They fall into the following different groups:

  • general main attributes
    • Manifest-Version: Defines the manifest file version. The value is a legitimate version number, as described in the above spec.
    • Created-By: Defines the version and the vendor of the java implementation on top of which this manifest file is generated. This attribute is generated by the jar tool.
    • Signature-Version: Defines the signature version of the jar file. The value should be a valid version-number string.
    • Class-Path: The value of this attribute specifies the relative URLs of the libraries that this application needs. URLs are separated by one or more spaces. The application class loader uses the value of this attribute to construct its internal search path. See Class-Path Attribute section for details.
    • Automatic-Module-Name: Defines the module name if this JAR file is deployed as an automatic module on the module path. For further details see the specification of automatic modules.
    • Multi-Release: This attribute defines whether this JAR file is a multi-release JAR file. If the value is "true" , case is ignored, then the JAR file will be processed by the Java runtime and tooling as a multi-release JAR file. Otherwise, if the value is anything other than "true" then this attribute is ignored.
  • attribute defined for stand-alone applications: This attribute is used by stand-alone applications that are bundled into executable jar files which can be invoked by the java runtime directly by running "java -jar x.jar".
    • Main-Class: The value of this attribute is the class name of the main application class which the launcher will load at startup time. The value must not have the .class extension appended to the class name.
    • Launcher-Agent-Class: If this attribute is present then its value is the class name of a java agent that is started before the application main method is invoked. This attribute can be used for cases where a java agent is packaged in the same executable JAR file as the application. The agent class defines a public static method name agentmain in one of the two forms specified in the java.lang.instrumentpackage summary. Additional attributes (such as Can-Retransform-Classes) can be used to indicate capabilities needed by the agent.
  • attributes defined for package versioning and sealing information: The value of these attributes apply to all the packages in the JAR file, but can be overridden by per-entry attributes.
    • Implementation-Title: The value is a string that defines the title of the extension implementation.
    • Implementation-Version: The value is a string that defines the version of the extension implementation.
    • Implementation-Vendor: The value is a string that defines the organization that maintains the extension implementation.
    • Specification-Title: The value is a string that defines the title of the extension specification.
    • Specification-Version: The value is a string that defines the version of the extension specification.
    • Specification-Vendor: The value is a string that defines the organization that maintains the extension specification.
    • Sealed: This attribute defines whether this JAR file is sealed or not. The value can be either "true" or "false", case is ignored. If it is set to "true", then all the packages in the JAR file are defaulted to be sealed, unless they are defined otherwise individually. See also the Package Sealing section.

Per-Entry Attributes

Per-entry attributes apply only to the individual JAR file entry to which the manifest entry is associated with. If the same attribute also appeared in the main section, then the value of the per-entry attribute overwrites the main attribute's value. For example, if JAR file a.jar has the following manifest content:

    Manifest-Version: 1.0
    Created-By: 1.8 (Oracle Inc.)
    Sealed: true
    Name: foo/bar/
    Sealed: false

It means that all the packages archived in a.jar are sealed, except that package foo.bar is not.

The per-entry attributes fall into the following groups:

  • attributes defined for file contents:
    • Content-Type: This attribute can be used to specify the MIME type and subtype of data for a specific file entry in the JAR file. The value should be a string in the form of type/subtype. For example "image/bmp" is an image type with a subtype of bmp (representing bitmap). This would indicate the file entry as an image with the data stored as a bitmap. RFC 1521 and 1522 discuss and define the MIME types definition.
  • attributes defined for package versioning and sealing information: These are the same set of attributes defined above as main attributes that defines the extension package versioning and sealing information. When used as per-entry attributes, these attributes overwrites the main attributes but only apply to the individual file specified by the manifest entry.
  • attribute defined for beans objects:
    • Java-Bean: Defines whether the specific jar file entry is a Java Beans object or not. The value should be either "true" or "false", case is ignored.
  • attributes defined for signing: These attributes are used for signing and verifying purposes. More details here.
    • x-Digest-y: The name of this attribute specifies the name of the digest algorithm used to compute the digest value for the corresponding jar file entry. The value of this attribute stores the actual digest value. The prefix 'x' specifies the algorithm name and the optional suffix 'y' indicates to which language the digest value should be verified against.
    • Magic: This is an optional attribute that can be used by applications to indicate how verifier should compute the digest value contained in the manifest entry. The value of this attribute is a set of comma separated context specific strings. Detailed description is here.

Signed JAR File

Overview

A JAR file can be signed by using the command line jarsigner tool or directly through the java.security API. Every file entry, including non-signature related files in the META-INF directory, will be signed if the JAR file is signed by the jarsigner tool. The signature related files are:

  • META-INF/MANIFEST.MF
  • META-INF/*.SF
  • META-INF/*.DSA
  • META-INF/*.RSA
  • META-INF/SIG-*

Note that if such files are located in META-INF subdirectories, they are not considered signature-related. Case-insensitive versions of these filenames are reserved and will also not be signed.

Subsets of a JAR file can be signed by using the java.security API. A signed JAR file is exactly the same as the original JAR file, except that its manifest is updated and two additional files are added to the META-INFdirectory: a signature file and a signature block file. When jarsigner is not used, the signing program has to construct both the signature file and the signature block file.

For every file entry signed in the signed JAR file, an individual manifest entry is created for it as long as it does not already exist in the manifest. Each manifest entry lists one or more digest attributes and an optional Magic attribute.

Signature File

Each signer is represented by a signature file with extension .SF. The major part of the file is similar to the manifest file. It consists of a main section which includes information supplied by the signer but not specific to any particular jar file entry. In addition to the Signature-Version and Created-By attributes (see Main Attributes), the main section can also include the following security attributes:

  • x-Digest-Manifest-Main-Attributes (where x is the standard name of a java.security.MessageDigest algorithm): The value of this attribute is the digest value of the main attributes of the manifest.
  • x-Digest-Manifest (where x is the standard name of a java.security.MessageDigest algorithm): The value of this attribute is the digest value of the entire manifest.

The main section is followed by a list of individual entries whose names must also be present in the manifest file. Each individual entry must contain at least the digest of its corresponding entry in the manifest file.

Paths or URLs appearing in the manifest file but not in the signature file are not used in the calculation.

Signature Validation

A successful JAR file verification occurs if the signature(s) are valid, and none of the files that were in the JAR file when the signatures were generated have been changed since then. JAR file verification involves the following steps:

  1. Verify the signature over the signature file when the manifest is first parsed. For efficiency, this verification can be remembered. Note that this verification only validates the signature directions themselves, not the actual archive files.

  2. If an x-Digest-Manifest attribute exists in the signature file, verify the value against a digest calculated over the entire manifest. If more than one x-Digest-Manifest attribute exists in the signature file, verify that at least one of them matches the calculated digest value.

  3. If an x-Digest-Manifest attribute does not exist in the signature file or none of the digest values calculated in the previous step match, then a less optimized verification is performed:

    1. If an x-Digest-Manifest-Main-Attributes entry exists in the signature file, verify the value against a digest calculated over the main attributes in the manifest file. If this calculation fails, then JAR file verification fails. This decision can be remembered for efficiency. If an x-Digest-Manifest-Main-Attributes entry does not exist in the signature file, its nonexistence does not affect JAR file verification and the manifest main attributes are not verified.

    2. Verify the digest value in each source file information section in the signature file against a digest value calculated against the corresponding entry in the manifest file. If any of the digest values don't match, then JAR file verification fails.

    One reason the digest value of the manifest file that is stored in the x-Digest-Manifest attribute may not equal the digest value of the current manifest file is that one or more files were added to the JAR file (using the jar tool) after the signature (and thus the signature file) was generated. When the jar tool is used to add files, the manifest file is changed (sections are added to it for the new files), but the signature file is not. A verification is still considered successful if none of the files that were in the JAR file when the signature was generated have been changed since then, which is the case if the digest values in the non-header sections of the signature file equal the digest values of the corresponding sections in the manifest file.

  4. For each entry in the manifest, verify the digest value in the manifest file against a digest calculated over the actual data referenced in the "Name:" attribute, which specifies either a relative file path or URL. If any of the digest values don't match, then JAR file verification fails.

Example manifest file:

    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)

The corresponding signature file would be:

    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)

The Magic Attribute

Another requirement to validate the signature on a given manifest entry is that the verifier understand the value or values of the Magic key-pair value in that entry's manifest entry.

The Magic attribute is optional but it is required that a parser understand the value of an entry's Magic key if it is verifying that entry's signature.

The value or values of the Magic attribute are a set of comma-separated context-specific strings. The spaces before and after the commas are ignored. Case is ignored. The exact meaning of the magic attributes is application specific. These values indicate how to compute the hash value contained in the manifest entry, and are therefore crucial to the proper verification of the signature. The keywords may be used for dynamic or embedded content, multiple hashes for multilingual documents, etc.

Here are two examples of the potential use of Magic attribute in the manifest file:

        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

In the first example, these Magic values may indicate that the result of an http query is the script embedded in the document, as opposed to the document itself, and also that the script is generated dynamically. These two pieces of information indicate how to compute the hash value against which to compare the manifest's digest value, thus comparing a valid signature.

In the second example, the Magic value indicates that the document retrieved may have been content-negotiated for a specific language, and that the digest to verify against is dependent on which language the document retrieved is written in.

Digital Signatures

A digital signature is a signed version of the .SF signature file. These are binary files not intended to be interpreted by humans.

Digital signature files have the same filenames as the .SF files but different extensions. The extension varies depending on the type of digital signature.

  • .RSA (PKCS7 signature, SHA-256 + RSA)
  • .DSA (PKCS7 signature, DSA)

Digital signature files for signature algorithms not listed above must reside in the META-INF directory and have the prefix "SIG-". The corresonding signature file (.SF file) must also have the same prefix.

For those formats that do not support external signed data, the file shall consist of a signed copy of the .SF file. Thus some data may be duplicated and a verifier should compare the two files.

Formats that support external data either reference the .SF file, or perform calculations on it with implicit reference.

Each .SF file may have multiple digital signatures, but those signatures should be generated by the same legal entity.

File name extensions may be 1 to 3 alphanum characters. Unrecognized extensions are ignored.

Notes on Manifest and Signature Files

Following is a list of additional restrictions and rules that apply to manifest and signature files.

  • Before parsing:
    • If the last character of the file is an EOF character (code 26), the EOF is treated as whitespace. Two newlines are appended (one for editors that don't put a newline at the end of the last line, and one so that the grammar doesn't have to special-case the last entry, which may not have a blank line after it).
  • Attributes:
    • In all cases for all sections, attributes which are not understood are ignored.
    • Attribute names are case insensitive. Programs which generate manifest and signature files should use the cases shown in this specification however.
    • Attribute names cannot be repeated within a section.
  • Versions:
    • Manifest-Version and Signature-Version must be first, and in exactly that case (so that they can be recognized easily as magic strings). Other than that, the order of attributes within a main section is not significant.
  • Ordering:
    • The order of individual manifest entries is not significant.
    • The order of individual signature entries is not significant, except that the digests that get signed are in that order.
  • Line length:
    • No line may be longer than 72 bytes (not characters), in its UTF8-encoded form. If a value would make the initial line longer than this, it should be continued on extra lines (each starting with a single SPACE).
  • Errors:
    • If a file cannot be parsed according to this spec, a warning should be output, and none of the signatures should be trusted.
  • Limitations:
    • Because header names cannot be continued, the maximum length of a header name is 70 bytes (there must be a colon and a SPACE after the name).
    • NUL, CR, and LF can't be embedded in header values, and NUL, CR, LF and ":" can't be embedded in header names.
    • Implementations should support 65535-byte (not character) header values, and 65535 headers per file. They might run out of memory, but there should not be hard-coded limits below these values.
  • Signers:
    • It is technically possible that different entities may use different signing algorithms to share a single signature file. This violates the standard, and the extra signature may be ignored.
  • Algorithms:
    • No digest algorithm or signature algorithm is mandated by this standard. However, at least one of SHA-256 and SHA1 digest algorithm must be supported.

JAR Index

Overview

Since 1.3, JarIndex is introduced to optimize the class searching process of class loaders for network applications, especially applets. Originally, an applet class loader uses a simple linear search algorithm to search each element on its internal search path, which is constructed from the "ARCHIVE" tag or the "Class-Path" main attribute. The class loader downloads and opens each element in its search path, until the class or resource is found. If the class loader tries to find a nonexistent resource, then all the jar files within the application or applet will have to be downloaded. For large network applications and applets this could result in slow startup, sluggish response and wasted network bandwidth. The JarIndex mechanism collects the contents of all the jar files defined in an applet and stores the information in an index file in the first jar file on the applet's class path. After the first jar file is downloaded, the applet class loader will use the collected content information for efficient downloading of jar files.

The existing jar tool is enhanced to be able to examine a list of jar files and generate directory information as to which classes and resources reside in which jar file. This directory information is stored in a simple text file named INDEX.LIST in the META-INF directory of the root jar file. When the classloader loads the root jar file, it reads the INDEX.LIST file and uses it to construct a hash table of mappings from file and package names to lists of jar file names. In order to find a class or a resource, the class loader queries the hashtable to find the proper jar file and then downloads it if necessary.

Once the class loader finds a INDEX.LIST file in a particular jar file, it always trusts the information listed in it. If a mapping is found for a particular class, but the class loader fails to find it by following the link, an unspecified Error or RuntimeException is thrown. When this occurs, the application developer should rerun the jar tool on the extension to get the right information into the index file.

To prevent adding too much space overhead to the application and to speed up the construction of the in-memory hash table, the INDEX.LIST file is kept as small as possible. For classes with non-null package names, mappings are recorded at the package level. Normally one package name is mapped to one jar file, but if a particular package spans more than one jar file, then the mapped value of this package will be a list of jar files. For resource files with non-empty directory prefixes, mappings are also recorded at the directory level. Only for classes with null package name, and resource files which reside in the root directory, will the mapping be recorded at the individual file level.

Index File Specification

The INDEX.LIST file contains one or more sections each separated by a single blank line. Each section defines the content of a particular jar file, with a header defining the jar file path name, followed by a list of package or file names, one per line. All the jar file paths are relative to the code base of the root jar file. These path names are resolved in the same way as the current extension mechanism does for bundled extensions.

The UTF-8 encoding is used to support non ASCII characters in file or package names in the index file.

Specification

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}

The INDEX.LIST file is generated by running jar -i. See the jar man page for more details.

Backward Compatibility

The new class loading scheme is totally backward compatible with applications developed on top of the current extension mechanism. When the class loader loads the first jar file and an INDEX.LIST file is found in the META-INF directory, it would construct the index hash table and use the new loading scheme for the extension. Otherwise, the class loader will simply use the original linear search algorithm.

Class-Path Attribute

The manifest for an application can specify one or more relative URLs referring to the JAR files and directories for other libraries that it needs. These relative URLs will be treated relative to the code base that the containing application was loaded from.

An application (or, more generally, JAR file) specifies the relative URLs of the libraries that it needs via the manifest attribute Class-Path. This attribute lists the URLs to search for implementations of other libraries if they cannot be found on the host Java Virtual Machine. These relative URLs may include JAR files and directories for any libraries or resources needed by the application. Relative URLs not ending with '/' are assumed to refer to JAR files. For example,

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

At most one Class-Path header may be specified in a JAR file's manifest..

Currently, the URLs must be relative to the code base of the JAR file for security reasons. Thus, remote optional packages will originate from the same code base as the application.

Each relative URL is resolved against the code base that the containing application or library was loaded from. If the resulting URL is invalid or refers to a resource that cannot be found then it is ignored.

The resulting URLs are used to extend the class path for the application, applet, or servlet by inserting the URLs in the class path immediately following the URL of the containing JAR file. Any duplicate URLs are omitted. For example, given the following class path:

a.jar b.jar

If b.jar contained the following Class-Path manifest attribute:

Class-Path: x.jar a.jar

Then the resulting application class path would be the following:

a.jar b.jar x.jar

Of course, if x.jar had dependencies of its own then these would be added according to the same rules and so on for each subsequent URL. In the actual implementation, JAR file dependencies are processed lazily so that the JAR files are not actually opened until needed.

Package Sealing

JAR files and packages can be optionally sealed, so that an package can enforce consistency within a version.

A package sealed within a JAR specifies that all classes defined in that package must originate from the same JAR. Otherwise, a SecurityException is thrown.

A sealed JAR specifies that all packages defined by that JAR are sealed unless overridden specifically for a package.

A sealed package is specified via the manifest attribute, Sealed, whose value is true or false (case irrelevant). For example,

    Name: javax/servlet/internal/
    Sealed: true

specifies that the javax.servlet.internal package is sealed, and that all classes in that package must be loaded from the same JAR file.

If this attribute is missing, the package sealing attribute is that of the containing JAR file.

A sealed JAR is specified via the same manifest header, Sealed, with the value again of either true or false. For example,

    Sealed: true

specifies that all packages in this archive are sealed unless explicitly overridden for a particular package with the Sealed attribute in a manifest entry.

If this attribute is missing, the JAR file is assumed to not be sealed, for backwards compatibility. The system then defaults to examining package headers for sealing information.

Package sealing is also important for security, because it restricts access to package-protected members to only those classes defined in the package that originated from the same JAR file.

The unnamed package is not sealable, so classes that are to be sealed must be placed in their own packages.

官方中文介紹*******************************************************************************************

介紹

JAR文件是基於流行的ZIP文件格式的文件格式,用於將許多文件聚合爲一個。JAR文件本質上是一個包含可選META-INF目錄的zip文件。JAR文件可以通過命令行jar工具創建,也可以使用java.util.jarJava平臺中的API創建。對JAR文件的名稱沒有限制,它可以是特定平臺上的任何合法文件名。

模塊化JAR文件

模塊化JAR文件是module-info.class在頂級目錄(或根目錄)目錄中具有模塊描述符的JAR文件。模塊描述符是模塊聲明的二進制形式。(注意有關多版本JAR文件的部分進一步細化了模塊化JAR文件的定義。)

部署在模塊路徑上的模塊化JAR文件(與類路徑相對)是一個顯式模塊。依賴項和服務提供程序在模塊描述符中聲明。如果模塊化JAR文件部署在類路徑上,那麼它的行爲就像非模塊化JAR文件一樣。

部署在模塊路徑上的非模塊化JAR文件是自動模塊。如果JAR文件具有主屬性Automatic-Module-Name(請參閱主要屬性),則屬性的值是模塊名稱,否則模塊名稱是從中指定的JAR文件的名稱派生的ModuleFinder.of(Path...)

多版本JAR文件

多版本JAR文件允許單個JAR文件支持多個主要版本的Java平臺版本。例如,多版本JAR文件可以依賴於Java 8和Java 9主要平臺版本,其中一些類文件依賴於Java 8中的API,而其他類文件依賴於Java 9中的API。這使庫和框架開發人員成爲可能將Java平臺版本的特定主要版本中的API的使用與其所有用戶遷移到該主要版本的要求分離。庫和框架開發人員可以逐步遷移並支持新的Java功能,同時仍支持舊功能。

主要屬性標識多版本JAR文件:

Multi-Release: true

JAR清單的主要部分宣佈。

依賴於Java平臺版本的主要版本(9或更高版本)的類和資源文件可以位於版本化目錄下,而不是位於頂級(或根目錄)目錄下。版本化目錄位於META-INF目錄下,格式如下:

META-INF/versions/N

其中N是Java平臺發行版主要版本號的字符串表示形式。具體N必須符合規範:

N: {1-9} {0-9}*

任何版本化的目錄,其值N小於,將9被忽略,因爲它的字符串表示N不符合上述規範。

版本化目錄下的類文件(N例如,在多版本JAR中)必須具有小於或等於與NJava平臺版本的主要版本相關聯的類文件版本的類文件版本。如果類文件的類是公共的或受保護的,那麼該類必須主持一個相同的完全限定名稱和訪問修飾符的類,其類文件存在於頂級目錄下。通過邏輯擴展,這適用於類文件的類(如果存在),在版本小於的版本化目錄下N

如果在Java平臺發佈運行時的主要版本的類路徑或模塊路徑(作爲自動模塊或顯式多發佈模塊)上部署多版本JAR文件N,則從該JAR文件加載類的類加載器將首先搜索N版本化目錄下的類文件,然後按降序排列先前版本的目錄(如果存在),下載到較低的主要版本9,最後搜索頂級目錄。

多版本JAR文件中的類導出的公共API在不同版本中必須完全相同,因此至少爲什麼版本化目錄下的類文件的版本化公共類或受保護類必須主持類頂層下的類文件的類 -級別目錄。執行廣泛的API驗證檢查既困難又昂貴,因爲這樣的工具(例如jar工具)不需要執行大量驗證,並且不需要Java運行時來執行任何驗證。此規範的未來版本可能會放寬完全相同的API約束以支持細緻的演變。

META-INF目錄下的資源無法進行版本控制(例如用於服務配置)。

可以簽署多版本JAR文件。

Java運行時的引導類加載器不支持多版本JAR文件。如果將多版本JAR文件附加到引導類路徑(使用該-Xbootclasspath/a選項),則將JAR視爲普通JAR文件。

模塊化多版本JAR文件

模塊化多版本JAR文件是一個多版本JAR文件,它具有模塊描述符module-info.class,位於頂級目錄(對於模塊化 JAR文件),或直接位於版本化目錄中。

非導出包中的公共或受保護類(未聲明爲在模塊描述符中導出)不需要主持一個相同的完全限定名稱和訪問修飾符的類,其類文件存在於頂級目錄下。

模塊描述符通常與任何其他類或資源文件的處理方式沒有區別。模塊描述符可以存在於版本化區域下但不存在於頂級目錄下。例如,這確保了只有Java 8版本化的類可以存在於頂級目錄下,而Java 9版本化的類(包括或者可能只是模塊描述符)可以存在於9版本化目錄下。

任何版本化的模塊描述符,主持較小的版本化模塊描述符,或者在頂層,M例如,必須相同M,但有兩個例外:

  1. 主持版本化描述符可以具有不同的transitive requires子句java.*jdk.*模塊; 和
  2. 主持版本描述符可以具有不同的uses條款,甚至之外定義服務類型java.*jdk.*模塊。

工具(例如jar工具)應該對版本化模塊描述符執行此類驗證,但不需要Java運行時來執行任何驗證。

META-INF目錄

Java 2平臺可識別和解釋META-INF目錄中的以下文件/目錄,以配置應用程序,類加載器和服務:

  • MANIFEST.MF

清單文件,用於定義與包相關的數據。

  • INDEX.LIST

此文件由-i"jar工具的新選項生成,該選項包含應用程序中定義的包的位置信息。它是JarIndex實現的一部分,並由類加載器用於加速其類加載過程。

  • x.SF

JAR文件的簽名文件。'x'代表基本文件名。

  • x.DSA

與簽名文件關聯的簽名塊文件具有相同的基本文件名。該文件存儲相應簽名文件的數字簽名。

  • services/

此目錄存儲部署在類路徑上的JAR文件的所有服務提供者配置文件或部署爲模塊路徑上的自動模塊的JAR文件。有關更多詳細信息,請參閱服務提供商開發規範。

  • versions/

該目錄下面包含多版本 JAR文件的版本化類和資源文件。

名稱 - 值對和部分

在我們詳細介紹各個配置文件的內容之前,需要定義一些格式約定。在大多數情況下,清單文件和簽名文件中包含的信息表示爲受RFC822標準啓發的所謂“名稱:值”對。我們還稱這些對標題或屬性。

名稱 - 值對的組稱爲“部分”。截面用空行與其他部分分開。

任何形式的二進制數據表示爲base64。二進制數據需要連續,這導致行長度超過72個字節。二進制數據的示例是摘要和簽名。

實現應支持最多65535字節的標頭值。

本文檔中的所有規範使用相同的語法,其中終端符號以固定寬度字體顯示,而非終端符號以斜體字體顯示。

規格:

部分: *標題+換行符
非空段: +標題+換行符
新隊: CR LF | LF | CR沒有跟着 LF
標題: 名稱 : 
名稱: alphanum * headerchar
值: SPACE * otherchar換行符*延續
延續: SPACE * otherchar換行符
alphanum: A-Z} | { a-z} | { 0-9}
headerchar: alphanum | -|_
otherchar:  之外的任何UTF-8字符NUL, CR LF
  • 注意:爲防止通過直接電子郵件發送文件,不會以四個字母“From”開頭。

上述規範中定義的非終端符號將在以下規範中引用。

JAR清單

概觀

JAR文件清單包含一個主要部分,後跟各個JAR文件條目的部分列表,每個部分由換行符分隔。主要部分和各個部分都遵循上面指定的部分語法。他們每個人都有自己的特定限制和規則。

  • 主要部分包含有關JAR文件本身以及應用程序的安全性和配置信息。它還定義了適用於每個單獨清單條目的主要屬性。此部分中的任何屬性都不能使其名稱等於“ Name”。此部分以空行終止。

  • 各個部分定義此JAR文件中包含的包或文件的各種屬性。並非JAR文件中的所有文件都需要作爲條目列在清單中,但必須列出要簽名的所有文件。不得列出清單文件本身。每個部分必須以名稱爲“ Name” 的屬性開頭,並且值必須是文件的相對路徑,或者是引用存檔外部數據的絕對URL。

  • 如果同一文件條目有多個單獨的部分,則合併這些部分中的屬性。如果某個屬性在不同的部分中具有不同的值,則會識別最後一個屬性。

  • 忽略不理解的屬性。這些屬性可以包括應用程序使用的實現特定信息。

清單規格:

清單文件: 主要部分換行*個別部分
主部: version-info newline * main-attribute
版本信息: Manifest-Version : 版本號
版本號: 數字+ { .數字+} *
主要屬性: (任何合法的主要屬性)換行符
個別部分: Name :  換行* perentry-attribute
perentry屬性: (任何合法的perentry屬性)換行符
新隊: CR LF | LF | CR沒有跟着 LF
數字: {0-9}

在上面的規範中,可以出現在主要部分中的屬性被稱爲主要屬性,而可以出現在各個部分中的屬性被稱爲每個條目屬性。某些屬性可以出現在主要部分和各個部分中,在這種情況下,每個條目屬性值將覆蓋指定條目的主要屬性值。兩種類型的屬性定義如下。

主要屬性

主要屬性是清單主要部分中存在的屬性。他們屬於以下不同的羣體:

  • 一般主要屬性
    • 清單 - 版本:定義清單文件版本。該值是合法的版本號,如上面的規範中所述。
    • Created-By:定義生成此清單文件的java實現的版本和供應商。該屬性由該jar工具生成。
    • 簽名版本:定義jar文件的簽名版本。該值應爲有效的版本號字符串。
    • Class-Path:此屬性的值指定此應用程序所需的庫的相對URL。URL由一個或多個空格分隔。應用程序類加載器使用此屬性的值來構造其內部搜索路徑。有關詳細信息,請參閱類路徑屬性部分。
    • Automatic-Module-Name:如果將此JAR文件部署爲模塊路徑上的自動模塊,則定義模塊名稱。有關詳細信息,請參閱規範automatic modules
    • Multi-Release:此屬性定義此JAR文件是否爲多版本 JAR文件。如果值爲“true”,則忽略大小寫,然後Java運行時和工具將JAR文件作爲多版本JAR文件進行處理。否則,如果該值不是“true”,則忽略此屬性。
  • 爲獨立應用程序定義的屬性:此屬性由捆綁到可執行jar文件的獨立應用程序使用,可由java運行時直接通過運行“ java -jar x.jar” 來調用。
    • Main-Class:此屬性的值是啓動時啓動程序將加載的主應用程序類的類名。該值不能.class擴展名附加到類名。
    • Launcher-Agent-Class:如果存在此屬性,則其值是在調用應用程序main方法之前啓動的java代理的類名。此屬性可用於將java代理程序打包在與應用程序相同的可執行JAR文件中的情況。agent類agentmainjava.lang.instrument包摘要中指定的兩種形式之一定義公共靜態方法名稱。其他屬性(例如Can-Retransform-Classes)可用於指示代理所需的功能。
  • 包版本控制和密封信息定義的屬性:這些屬性的值適用於JAR文件中的所有包,但可以由每個條目屬性覆蓋。
    • Implementation-Title:值是一個字符串,用於定義擴展實現的標題。
    • Implementation-Version:該值是一個字符串,用於定義擴展實現的版本。
    • Implementation-Vendor:該值是一個字符串,用於定義維護擴展實現的組織。
    • Specification-Title:該值是一個字符串,用於定義擴展規範的標題。
    • Specification-Version:該值是一個字符串,用於定義擴展規範的版本。
    • 規範 - 供應商:該值是一個字符串,用於定義維護擴展規範的組織。
    • 密封:此屬性定義此JAR文件是否已密封。值可以是“true”或“false”,大小寫將被忽略。如果將其設置爲“true”,則JAR文件中的所有包都將被默認爲密封,除非它們是單獨定義的。另請參閱包裝密封部分。

每個條目屬性

每個條目屬性僅適用於與清單條目關聯的單個JAR文件條目。如果主要部分中也出現相同的屬性,則per-entry屬性的值將覆蓋主要屬性的值。例如,如果JAR文件a.jar具有以下清單內容:

    Manifest-Version: 1.0
    Created-By: 1.8 (Oracle Inc.)
    Sealed: true
    Name: foo/bar/
    Sealed: false

這意味着在a.jar中存檔的所有包都是密封的,除了包foo.bar不是。

每個條目屬性分爲以下幾組:

  • 爲文件內容定義的屬性:
    • Content-Type:此屬性可用於爲JAR文件中的特定文件條目指定MIME類型和數據子類型。該值應爲type / subtype形式的字符串例如,“image / bmp”是具有bmp子類型(表示位圖)的圖像類型。這將指示文件條目作爲圖像,其中數據存儲爲位圖。RFC 15211522討論並定義了MIME類型定義。
  • 爲包版本控制和密封信息定義的屬性:這些屬性是上面定義的相同屬性集,用於定義擴展包版本控制和密封信息的主要屬性。當用作每個條目屬性時,這些屬性會覆蓋主要屬性,但僅適用於清單條目指定的單個文件。
  • 爲bean對象定義的屬性:
    • Java-Bean:定義特定的jar文件條目是否是Java Beans對象。該值應爲“true”或“false”,大小寫將被忽略。
  • 爲簽名定義的屬性:這些屬性用於簽名和驗證目的。更多細節在這裏。
    • x-Digest-y:此屬性的名稱指定用於計算相應jar文件條目的摘要值的摘要算法的名稱。此屬性的值存儲實際摘要值。前綴“x”指定算法名稱,可選後綴“y”指示應該針對哪種語言驗證摘要值。
    • Magic:這是一個可選屬性,應用程序可以使用它來指示驗證者應如何計算清單條目中包含的摘要值。此屬性的值是一組逗號分隔的上下文特定字符串。詳細說明如下。

簽名的JAR文件

概觀

可以使用命令行jarsigner工具或直接通過java.securityAPI 對JAR文件進行簽名。META-INF如果JAR文件由jarsigner工具簽名,則將對每個文件條目(包括目錄中的非簽名相關文件)進行簽名。簽名相關文件是:

  • META-INF/MANIFEST.MF
  • META-INF/*.SF
  • META-INF/*.DSA
  • META-INF/*.RSA
  • META-INF/SIG-*

請注意,如果此類文件位於META-INF子目錄中,則不會將其視爲與簽名相關。這些文件名的不區分大小寫的版本是保留的,也不會簽名。

可以使用java.securityAPI 對JAR文件的子集進行簽名。簽名的JAR文件與原始JAR文件完全相同,只是更新其清單並將另外兩個文件添加到META-INF目錄中:簽名文件和簽名塊文件。當不使用jarsigner時,簽名程序必須構造簽名文件和簽名塊文件。

對於在簽名的JAR文件中籤名的每個文件條目,只要清單中不存在單個清單條目,就會爲其創建單獨的清單條目。每個清單條目都列出一個或多個摘要屬性和可選的Magic屬性

簽名文件

每個簽名者由具有擴展名的簽名文件表示.SF。該文件的主要部分類似於清單文件。它由一個主要部分組成,其中包括簽名者提供的信息,但不是特定於任何特定的jar文件條目。除了Signature-VersionCreated-By屬性(請參閱主要屬性)之外,主要部分還可以包括以下安全屬性:

  • x-Digest-Manifest-Main-Attributes(其中x是java.security.MessageDigest算法的標準名稱):此屬性的值是清單主要屬性的摘要值。
  • x-Digest-Manifest(其中x是java.security.MessageDigest算法的標準名稱):此屬性的值是整個清單的摘要值。

主要部分後面是單個條目的列表,其名稱也必須出現在清單文件中。每個單獨的條目必須至少包含清單文件中其相應條目的摘要。

出現在清單文件中但未出現在簽名文件中的路徑或URL不會用於計算。

簽名驗證

如果簽名有效,則會發生成功的JAR文件驗證,從那時起,生成簽名時JAR文件中的所有文件都沒有更改。JAR文件驗證涉及以下步驟:

  1. 首次解析清單時,驗證簽名文件上的簽名。爲了提高效率,可以記住此驗證。請注意,此驗證僅驗證簽名方向本身,而不驗證實際的歸檔文件。

  2. 如果x-Digest-Manifest簽名文件中存在屬性,請針對在整個清單上計算的摘要驗證該值。如果x-Digest-Manifest簽名文件中存在多個屬性,請驗證其中至少有一個屬性與計算的摘要值匹配。

  3. 如果x-Digest-Manifest簽名文件中不存在屬性,或者上一步驟中計算的摘要值都不匹配,則執行不太優化的驗證:

    1. 如果x-Digest-Manifest-Main-Attributes簽名文件中存在條目,請根據清單文件中主要屬性計算的摘要驗證該值。如果此計算失敗,則JAR文件驗證失敗。可以記住這個決定的效率。如果x-Digest-Manifest-Main-Attributes簽名文件中不存在條目,則其不存在不會影響JAR文件驗證,並且不會驗證清單主要屬性。

    2. 根據清單文件中相應條目計算的摘要值,驗證簽名文件中每個源文件信息部分中的摘要值。如果任何摘要值不匹配,則JAR文件驗證失敗。

    存儲在x-Digest-Manifest屬性中的清單文件的摘要值可能不等於當前清單文件的摘要值的一個原因是簽名後將一個或多個文件添加到JAR文件(使用jar工具)(因此簽名文件)已生成。使用jar工具添加文件時,會更改清單文件(爲新文件添加部分),但簽名文件不會。如果從那時起生成簽名時JAR文件中沒有任何文件被更改,則驗證仍然被認爲是成功的,如果簽名文件的非標題部分中的摘要值等於摘要值,則情況就是這種情況清單文件中相應部分的內容。

  4. 對於清單中的每個條目,請根據“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密鑰對值的值。

Magic屬性是可選的,但要求解析器在驗證條目的簽名時才能理解條目的Magic密鑰的值。

Magic屬性的值是一組以逗號分隔的特定於上下文的字符串。逗號前後的空格將被忽略。案例被忽略。魔術屬性的確切含義是特定於應用程序的。這些值指示如何計算清單條目中包含的哈希值,因此對於正確驗證簽名至關重要。關鍵字可用於動態或嵌入內容,多語言文檔的多個哈希等。

以下是清單文件中可能使用Magic屬性的兩個示例:

        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查詢的結果是嵌入在文檔中的腳本,而不是文檔本身,以及腳本是動態生成的。這兩條信息指示如何計算用於比較清單的摘要值的哈希值,從而比較有效簽名。

在第二個示例中,Magic值表示檢索到的文檔可能已針對特定語言進行內容協商,並且要驗證的摘要取決於所檢索文檔所寫的語言。

數字簽名

數字簽名是.SF簽名文件的簽名版本。這些是不打算由人類解釋的二進制文件。

數字簽名文件與.SF文件具有相同的文件名,但擴展名不同。擴展名根據數字簽名的類型而有所不同。

  • .RSA (PKCS7簽名,SHA-256 + RSA)
  • .DSA (PKCS7簽名,DSA)

上面未列出的簽名算法的數字簽名文件必須位於META-INF目錄中,並帶有前綴“ SIG-”。相應的簽名文件(.SF文件)也必須具有相同的前綴。

對於那些不支持外部簽名數據的格式,該文件應包含該文件的簽名副本.SF。因此,一些數據可能被複制,驗證者應該比較這兩個文件。

支持外部數據的格式可以引用該.SF文件,也可以使用隱式引用對其執行計算。

每個.SF文件可能有多個數字簽名,但這些簽名應由同一法人實體生成。

文件擴展名可以是1到3 個字母數字字符。無法識別的擴展名將被忽略。

有關清單和簽名文件的說明

以下是適用於清單和簽名文件的其他限制和規則的列表。

  • 在解析之前:
    • 如果文件的最後一個字符是EOF字符(代碼26),則將EOF視爲空格。附加兩個換行符(一個用於不在最後一行末尾添加換行符的編輯器,另一個用於語法不必具有特殊情況的最後一個條目,其後可能沒有空行)。
  • 屬性:
    • 在所有部分的所有情況下,忽略不理解的屬性。
    • 屬性名稱不區分大小寫。生成清單和簽名文件的程序應該使用本規範中顯示的情況。
    • 屬性名稱不能在節中重複。
  • 版本:
    • 清單版本和簽名版本必須是第一個,並且在這種情況下(因此它們可以很容易地被識別爲魔術字符串)。除此之外,主要部分中的屬性順序並不重要。
  • 排序:
    • 單個清單條目的順序並不重要。
    • 單個簽名條目的順序並不重要,除了獲得簽名的摘要按此順序排列。
  • 線長:
    • 任何行都不能長於72字節(不是字符),採用UTF8編碼形式。如果某個值使初始行長於此值,則應在額外行上繼續(每個行以單個SPACE開頭)。
  • 錯誤:
    • 如果無法根據此規範解析文件,則應輸出警告,並且不應信任任何簽名。
  • 限制:
    • 由於標題名稱無法繼續,標題名稱的最大長度爲70個字節(名稱後必須有冒號和SPACE)。
    • NUL,CR和LF不能嵌入標題值中,並且NUL,CR,LF和“:”不能嵌入標題名稱中。
    • 實現應支持65535字節(非字符)標頭值,每個文件65535標頭。它們可能會耗盡內存,但不應低於這些值的硬編碼限制。
  • 簽名者:
    • 技術上可能的是,不同的實體可以使用不同的簽名算法來共享單個簽名文件。這違反了標準,可能會忽略額外的簽名。
  • 算法:
    • 本標準未強制要求摘要算法或簽名算法。但是,必須至少支持SHA-256和SHA1摘要算法之一。

JAR指數

概觀

從1.3開始,引入了JarIndex來優化類加載器的類搜索過程,用於網絡應用程序,尤其是applet。最初,applet類加載器使用簡單的線性搜索算法來搜索其內部搜索路徑上的每個元素,該搜索路徑是從“ARCHIVE”標記或“Class-Path”主要屬性構造的。類加載器下載並打開其搜索路徑中的每個元素,直到找到類或資源。如果類加載器試圖找到不存在的資源,則必須下載應用程序或applet中的所有jar文件。對於大型網絡應用程序和applet,這可能導致啓動緩慢,響應遲緩和網絡帶寬浪費。JarIndex機制收集applet中定義的所有jar文件的內容,並將信息存儲在applet類路徑上第一個jar文件的索引文件中。下載第一個jar文件後,applet類加載器將使用收集的內容信息有效下載jar文件。

現有jar工具已得到增強,能夠檢查jar文件列表並生成有關哪些類和資源駐留在哪個jar文件中的目錄信息。此目錄信息存儲在根jar文件INDEX.LISTMETA-INF目錄中命名的簡單文本文件中。當類加載器加載根jar文件時,它會讀取INDEX.LIST文件並使用它來構造從文件和包名到jar文件名列表的映射哈希表。爲了查找類或資源,類加載器查詢哈希表以查找正確的jar文件,然後在必要時下載它。

一旦類加載器INDEX.LIST在特定的jar文件中找到文件,它就始終信任其中列出的信息。如果找到特定類的映射,但類加載器無法通過鏈接找到它,則拋出未指定的Error或RuntimeException。發生這種情況時,應用程序開發人員應jar在擴展上重新運行該工具,以便將正確的信息輸入索引文件。

爲了防止嚮應用程序添加太多空間開銷並加快內存中哈希表的構造,INDEX.LIST文件保持儘可能小。對於具有非null包名稱的類,將在包級別記錄映射。通常,一個包名稱映射到一個jar文件,但如果特定包跨越多個jar文件,則此包的映射值將是jar文件的列表。對於具有非空目錄前綴的資源文件,映射也會記錄在目錄級別。僅對於具有空包名稱的類以及駐留在根目錄中的資源文件,將在單個文件級別記錄映射。

索引文件規範

INDEX.LIST文件包含一個或多個部分,每個部分由一個空行分隔。每個部分定義一個特定jar文件的內容,其中一個頭定義了jar文件的路徑名,後面是一個包或文件名列表,每行一個。所有jar文件路徑都相對於根jar文件的代碼庫。這些路徑名的解析方式與當前擴展機制對捆綁擴展的解析方式相同。

UTF-8編碼用於支持索引文件中文件或包名稱中的非ASCII字符。

規格

索引文件: 版本信息空白部分*
版本信息: JarIndex-Version: 版本號
版本號: 數字+ {位數字+} *
部分: 身體空白
身體: 標題名稱*
標題: char + .jar 換行符
名稱: char +換行符
焦炭:  之外的任何有效Unicode字符NULL, CR LF
空行: 換行換行符
新隊: CR LF | LF | CR沒有跟着 LF
數字: 0-9}

INDEX.LIST文件是通過運行生成jar -i.請參閱jar手冊頁以獲取更多詳細信息。

向後兼容性

新的類加載方案完全向後兼容在當前擴展機制之上開發的應用程序。當類加載器加載第一個jar文件並INDEX.LISTMETA-INF目錄中找到一個文件時,它將構造索引哈希表並使用新的加載方案進行擴展。否則,類加載器將簡單地使用原始線性搜索算法。

類路徑屬性

應用程序的清單可以指定一個或多個相對URL,引用它所需的其他庫的JAR文件和目錄。這些相對URL將相對於加載包含應用程序的代碼庫進行處理。

應用程序(或更一般地說,JAR文件)通過manifest屬性指定所需庫的相對URL Class-Path。如果在主機Java虛擬機上找不到其他庫的實現,則此屬性將列出用於搜索其他庫的實現的URL。這些相對URL可以包括應用程序所需的任何庫或資源的JAR文件和目錄。假設不以'/'結尾的相對URL引用JAR文件。例如,

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

最多Class-Path可以在JAR文件的清單中指定一個標頭。

目前,出於安全原因,URL必須對於JAR文件的代碼庫。因此,遠程可選包將源自與應用程序相同的代碼庫。

每個相對URL都是根據加載包含的應用程序或庫的代碼庫來解析的。如果生成的URL無效或引用了無法找到的資源,則會忽略該URL。

生成的URL用於通過在包含JAR文件的URL之後的類路徑中插入URL來擴展應用程序,applet或servlet的類路徑。省略任何重複的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定義的所有包都是密封的,除非專門針對包重寫。

密封包是通過manifest屬性指定的Sealed,其值爲truefalse(不相關)。例如,

    Name: javax/servlet/internal/
    Sealed: true

指定javax.servlet.internal包是密封的,並且必須從同一個JAR文件加載該包中的所有類。

如果缺少此屬性,則包密封屬性是包含JAR文件的屬性。

密封的JAR通過相同的清單頭指定Sealed,其值再次爲truefalse。例如,

    Sealed: true

指定此歸檔中的所有包都是密封的,除非顯式覆蓋Sealed具有清單條目中屬性的特定包。

如果缺少此屬性,則假定JAR文件未被密封,以實現向後兼容性。然後,系統默認檢查包頭是否有密封信息。

程序包密封對於安全性也很重要,因爲它將對受程序包保護的成員的訪問限制爲僅在源自同一JAR文件的程序包中定義的那些類。

未命名的包不可密封,因此要密封的類必須放在它們自己的包中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章