Что такое jar файл в java
Перейти к содержимому

Что такое jar файл в java

  • автор:

Java Basics: JAR Files

JAR files are Java’s way of distributing libraries and executable programs. JAR is short for Java ARchive . JARs are just ZIP files with a .jar extension and a special directory structure. They can contain the programs or library’s classes as well as any other files they may need. A special file called /META-INF/MANIFEST.MF is often required to be in the archive and contains information about the JAR content, such as the name of the main class and its dependencies.

  • you want to bundle a Java application’s files for distribution, or
  • you need to deploy your code at a place where you need it as a JAR, or
  • you need to sign your code, for example to execute it in a web browser or on a cell phone

Java supports JARs since version 1.1 (in other words, practically forever).

Creating JARs

JARs are just ZIP files with a .jar extension and a special directory structure. Meta information is in a directory called META-INF , with the manifest file /META-INF/MANIFEST.MF being the most important file.

Beside META-INF , you add any file you want to the JAR file. Classes must be put into the usual Java directory structure.
This is an example layout for a JAR file, with a manifest file and two classes «com.jarfiller.example.MainClass» and «com.jarfiller.example.Helper»:

The manifest file ( /META-INF/MANIFEST.MF ) describes the content of the JAR file. It is not required, but often automatically added by JAR tools.
The following manifest declares only a main class:

Rules for Manifest Files
  • a manifest contains key/value pairs (called attributes ), one per line
  • attribute syntax: attribute name, directly followed by a colon (‘:’), a single space and the value
  • values may span several lines. Each additional line must start with one space.
  • no additional whitespace allowed (more)
  • no empty lines allowed in the main section (there can be additional sections, separated by empty lines)
Common Attributes
Name Description Example
Manifest-Version File format version of the manifest, always ‘1.0’, required 1.0
Main-Class Name of the class containing the main method in executable JARs my.package.MainClass
Class-Path Space-separated list of relative paths to JAR files and directories for the classpath lib/util.jar lib/helper.jar drivers/
Sealed if «true», then packages are sealed. Otherwise «false». true
Created-By Creator of the JAR; automatically added by the jar tool; not important 1.6.0_12 (Sun Microsystems Inc.)
Implementation-Title Name of the program/library contained in the JAR My Super App
Implementation-Version Version of the program/library contained in the JAR 1.0d
Implementation-Vendor Vendor of the program/library contained in the JAR Super Soft Inc.
Specification-Title Name of the specification the library implements (more) Super API
Specification-Version Version of the specification 1.0
Specification-Vendor Vendor of the specification Super Group

Beside those common attributes, there are many special purpose attributes. For example, if you package a Java Applet or a OSGi Bundle in a JAR, there are specific (and often required) attributes for them. For a simple library or executable JAR they are not needed though.

Example

The JDK ships with a command line tool called jar to create, view and unpack JAR files. On Windows, use it like this:

To create a JAR file from your compiled classes, enter:

To specify a manifest file, either put it into the base directory (would be workspace/JarTest/bin/META-INF/MANIFEST.MF ), or use the ‘m’ parameter:

How to.

Usually the .jar file extension is associated with the Java runtime. That means that just by double-clicking an executable JAR the application should start. Unfortunately executable JARs have the same extension as other JARs, such as libraries. So you can’t tell which JAR is executable, unless you look at its MANIFEST.MF file.

On the command line, you start an executable JAR by running java with the -jar option:

JARs are only ZIP files with a funny name, so you can view and unpack them with any ZIP tool. You may have to change its extension to ‘.zip’ before, if the tool does not recognize the JAR otherwise.
The jar tool shipped with the JDK also allows you to view and extract them on the command line. Use the ‘t’ command to view the content:

Unpack a JAR with the ‘x’ command:

Most JARs, no matter whether they contain an executable program or a library, require other libraries to run. Those dependencies are usually contained in JARs as well. So how can you make sure that your JAR has all required JARs in its CLASSPATH? There are three common solutions for executable JARs.

Solution 1: Using the Class-Path Attribute

The Class-Path attribute of the manifest file allows you to state a list of JARs that the Java runtime should put into its classpath. So basically your program consists of several JARs, one executable for the program itself and one JAR for each library.
This example shows a manifest file with several dependencies:

Note that your IDE may be able to create such a manifest and package your libraries automatically. For example, Eclipse can do this since version 3.5 (export your project as ‘Runnable JAR file’ and select the appropriate option).

Solution 2: Unpack Library JARs into a Single JAR

A nifty solution to the problem is to unpack all JARs you depend on and put them all into a single JAR. This works most of the time, but with some JARs, such as Service Providers, it won’t (more).

There are several tools that allow you to do this to various extends (e.g. they may not merge the manifests of the JARs correctly). Recent Eclipse versions can repack executable JARs. Just export the project into a ‘Runnable JAR file’ and select the right option.
Ant also allows you to unpack JARs into a single JAR using the jar task.

Solution 3: Call java with all JARs in the CLASSPATH

Another common solution is to write a script or batch file that puts all JARs into the classpath and then starts the application. This also allows you to add other arguments to the Java runtime (such as an increased heap) and state the main class (so you don’t need a special manifest). Then you start the application like this:

Dependencies for Library

Most libraries also depend on other libraries. Theoretically you could apply Solution 1 or Solution 2 to a library. This would be rather unusual though. Common practice is to state your dependencies somewhere in the documentation (or just have a directory containing dependencies) and let the library’s user take care of putting them into the classpath. Do not apply the solutions above to libraries.
The main reason is that the you (or, rather, the library’s user) needs to be sure to have every library only once in the classpath. With Solution 1, two JARs could depend on the same library, but use different names for it, and you end up with including the library twice. With Solution 2, several JARs could contain the same library. Both solutions get especially messy when different versions of the same library are involved.

Some JARs need to be signed, for example a JAR containing a Java Applet that requires certain privileges. Signing means that a digital signature is used to authenticate the author of the JAR. How exactly digital signatures work is out of the scope of this document (read the Wikipedia article as starting point), but what it effectively does is let somebody certify your identity. Idealy, but not necessarily, this somebody is a trusted certificate authority.

A digital signature has two main components. The first one is your private key that represents you. And then you need a certificate by somebody who certifies that you are who you claim to be. In the simplest case, you can create the certificate yourself. This is called a self-signed certificate. Obviously it is not very trustworthy, because anybody can certificate himself to be anybody. But for testing this is usually the easiest solution. Beside the lack of security, the major disadvantage of self-signed certificates is that the user will see a lot of warnings when installing your software, and may even be unable to install it without having system administrator privileges.

If you want to publish your software for the public, you should get a real certificate from a trusted certificate authority. The next how-to will help you get this, but for now, I show you how to create a self-signed certificate.

To sign a JAR, the first thing you need is the private key. Only you should own this key, as anybody who gets hold of it can claim to be you. Java stores keys in a file called keystore. You must assign each key in the keystore a name, called «alias» by Java (more). The main tool to manage keystores is a command line tool called keytool which ships with the JDK.

This is how to create a new key, either adding it to an existing keystore or creating a new one. The key will automatically be self-signed:

The command will ask you a couple of questions. First you can protect your keystore with a password, if you create a new one. You should do this if you plan to publish software with the keys in the keystore. Then it will ask you for your name, organization and location. This information is what will be shown to the user and possibly be certified by the certificate authority, so be careful to enter the right values.

Now that you have a (self-signed) key, you can easily sign your JAR with the jarsigner tool:

JAR File in Java

JAR file stands for Java ARchive file. Inspired by the popular zip files, Java provides JAR files for aggregating all the components like class files and the corresponding metadata of all the files which are packaged, including the resources of an application. This helps a client application to retrieve all the components in a single HTTP call which saves a lot of time (considering the case of a high ping network).

Scope

In this article

  • Let's have an introduction to the JAR files and their contents.
  • Have a look over working with JAR files.
  • Know about executable JAR files and create one.
  • Have a look at creating JAR files using maven and spring boot.

Introduction to JAR File in Java

Data compression is a must-do step in the current digital world, and the compression has to be lossless to maintain the integrity of the data. Now such flexibility in compressing the data has brought ease in transferring the files or archiving the files, but the speed at which things are getting digitalized demands a need for compression at the application level. The problem statement is to aggregate all the components of an application into a single file, such that all of them can be downloaded to a browser in a single HTTP call. And there's a way to do so using the Java ARchive files (JAR files).

JAR file helps a client application to retrieve all the components in a single HTTP call, which makes it capable of fetching multiple programs in a single file and hence saves a lot of time(considering the case of a high ping network).

JAR file maintains the essence of Java by providing support across all platforms, i.e., a JAR file created in one system can be used across all other systems with different OS. JAR files are open-source and developed using Java language. Edge devices with constrained computation like mobile phones often use them for storing the application files in compressed format.

Contents of a JAR File

A typical JAR file is capable to store .class files(compiled java code), .java files(java program files), supporting configuration files and metadata, and other resources like images, audio, text files, etc. This feature brings significance to the JAR files because usually, an application requires resources along with the program files. For example, a java swing application, a java gaming application, or any java application which has a user interaction interface makes it trivial to have image and audio file resources. Similarly, configuration files allow the user to configure the behavior of an application. For example, the main class of a java application can be configured such that executing the JAR file will invoke that class first.

Working with JAR Files

1. Creating a JAR File in Java

Now that we're aware of JAR files, let's create a JAR file in java.

Here's the command for creating a JAR file in java.

Let's have a detailed look at the above command. c denotes that we are trying to create a jar file, v stands for verbose (provides more information in the logs than the typical logs), it gives some details of the command onto the console, and f specifies to store the output of the command into the file specified in the command prompt. jar-filename is the name of the jar file in which the output of the command is saved. And the file-input is the path/filename of the file that has to be compressed into the JAR file.

Example:

The above code will compress the SampleJavaClass.class file into SampleJarFile.jar. We can directly specify the file name if the command prompt is opened in the current directory, else an absolute path has to be given. In our case we are considering the command prompt opened in the current directory.

2. Viewing a JAR File

Just like how a file system shows the contents of a folder, Java also provides a way to view the contents of a JAR file.

Executing the following command displays the contents of a JAR file.

Let's have a granular look over the command, t specifies to display the contents of the jar file in tabular format, and f specifies that the path/filename for the jar file is provided in the command prompt itself. And the jar-filename in the command expects the filename of the jar file of which the contents are to be displayed.

Example:

The above code willshow the contents of the SampleJarFIle.jar in a tabular manner.

3. Extracting a JAR File

The jar tool provides a lossless decompression and maintains the integrity of the data.

Here's the command for doing that using the jar tool.

Let's have a granular look over the command, x denotes that we are trying to extract the jar file, and f denotes that the jar filename is provided in the command prompt itself.

We can explicitly specify the files we want to extract.

The above command will only extract the SampleJavaClass.class from the SampleJarFile.jar.

Or we can extract the whole JAR file.

The above command will extract all the files from the SampleJarFile.jar.

The jar tool doesn't allow the creation of a JAR file without specifying the input files using the 'c' option. But if the program files inside a JAR are deleted manually, then the extracted folder of such file will have only a manifest file inside it which is created by default.

4. Updating a JAR File

Updating the JAR file includes operations like updating the metadata of the jar, adding a new file, etc.

The option u in the above command denotes that we are trying to update the jar file using the jar tool, and option f denotes that the filename of the jar is specified in the command prompt itself.

In the earlier examples we have created a jar file with only a single class file. Let's add another class file into the JAR file. And here's how to do that.

The above command will append the AddonJavaClass.class to the existing SampleJarFile.jar file.

Similarly adding a new file into a specific folder can also be done with the option u. Here’s the command for that

This command will rasie an error in the absence of the Addons folder. In a sunny day scenario, the above command will add the AddonJavaClass.class file to the Addon folder.

We can also edit the contents of a manifest file using the following command

This command will replace the key-value pairs of the SampleJarFile.jar's manifest file with the ones in the NewManifest.txt file.

5. Running a JAR File

Now that we've seen how to create, view, and update a jar file. Let's have a look at executing the jar files.

To Execute a JAR file as a java application, we have to specify the class name which includes the main method. And here's the code to do that.

In the above command -cp denotes classpath, and this command will invoke the specified class file. In the absence of the -cp argument, the jar tool will raise no main manifest attribute error.

For example, in our case consider SampleJavaClass is the main class and the command to execute our jar file is

The above command will execute the SampleJavaClass.class file. Can we execute a JAR without the -cp command?

Executable JAR Files

So far, we've created jar files and compressed the files into that jar files. We have explicitly mentioned the class name that has the main method for executing the jar file.

An executable jar file provides the flexibility to directly execute the jar file without using the -cp argument in the command line. Few operating systems like windows call the java main method when we double click on the JAR file icon. But how? These JAR files contain a manifest file that holds the information about the main class in the application. The manifest file includes a key-value pair to store the name of the main class. Here the key should be Main-Class, and the corresponding value should be the main class name.

How to Make an Executable JAR File in Java?

1. Create the Java File

Let's create a simple swing program in java.

To test the execution of the JAR file by double-clicking on the file icon, we have created a swing program since the output of a swing program is displayed on UI.

Here's our sample Java program:

Now to create the .class file, we have to compile the code using the following command.

The above command will compile the code and creates SimpleSwingExample.class file.

2. Generating a Manifest File

Let's create a text file to include the information about the main class name. And let's name it manifest.txt And here's the text to be added to the file.

After this step we'll have a new manifest.txt file. The Main-Class attribute should not be the last line of the file to avoid improper parsing. Add an empty line at the end.

3. Generating the Executable JAR

Now that we've created the manifest, let's create the JAR file. To do that, we have to specify this text file name in the command line while creating the jar file. And here's the code to do that

We can also create an executable JAR file by specifying the MainClass name in the command while creating the JAR file. And here's the comand to do that.

The option e in the above command denotes the entry point of the JAR file.

To execute the above jar files, we've to run the following command

Or double click on the JAR file icon, supported by a few operating systems like windows. And executing the jar file will open the following GUI.

Java Archive Apps

When we install JDK in windows, it provides a few predefined exe files like javac.exe, java.exe, and jar.exe inside the bin folder. Among them, jar.exe is the reason why we don't need to explicitly download any application or tool for performing actions on JAR files.

The jar.exe or the jar tool allows performing a few actions like creating, extracting, and updating the JAR files.

JAR File Openers

The contents of a JAR file can be extracted using the jar tool by the following command.

Executing the above command will write the contents of the jar file into the current directory. In our case, the above command will write SampleJavaClass.class, AddonJavaClass.class , and META-INF folder into the current directory. Remember that if the current directory has a file that clashes with any of the file names in the JAR file, then extracting the JAR file will override that file with the one in the JAR file.

Or by simply renaming the extension .jar to .zip and using the zip file decompressing tools to extract the contents of a JAR file.

The Java JAR Command

The jar tool or the jar utility provided by the java development kit made it easy with the JAR file handling. The jar tool entitles the user the flexibility of creating a JAR file by running a single line command, Similarly to updating and viewing the JAR files as well.

Manifest Files in JAR

When a new JAR file is created, it creates a folder META/INF and file MANIFEST.MF, inside the folder. The manifest file is configurable and is created by default when we create a new JAR file. This manifest file includes information about the contents of the JAR and the corresponding metadata. This file is encoded in UTF-8 encoding and it is restricted to having a single such file in that folder.

Manifest files allow the user to execute a JAR file without using the -cp argument in the command prompt, which in turn improves the usability of an application. Manifest files also improve the ease of updating the JAR files.

Package Sealing in Java

In general, term sealing means to lock or close securely. In the view of programming, sealing a program file means locking the content of a program file. A JAR file in Java can also be sealed. And sealing a JAR file brings a restriction to archive all the classes in the package to the same JAR file. This process works as a version control system, and any changes made to the JAR file should be reflected in a new JAR file. Sealing is done by mentioning the package name in the manifest file with an argument Sealed: true.

Here are the changes to be made in the manifest file. We can explicitly mention the package name to seal only those packages.

Remember the package name in the manifest file must end with a '/'

Or we can seal the whole package with a single argument Sealed: true.

Sealing also supports the vice versa situation of sealing the whole package with an exemption for few a packages like this.

The above changes in manifest file seals the whole JarDemo package and excludes the PackageTwo package.

Using Maven to Create JAR File

Maven provides a plugin for creating the JAR files. All the configuration for the JAR file has to be configured in the XML. The manifest file can also be configured in the XML itself, this provides the flexibility to specify the main class in the configuration itself or specify explicitly using the -cp argument.

After creating a maven project, the maven-jar-plugin plugin has to be included in the pom.xml file.

Here's the following changes to be made in the pom.xml for creating an executable JAR file.

POM stands for Project Object Model, which stores all the configuration details and information about a maven project.

Similarly here's the code for Main.java

Now that we've created the java file and added the plugin to the pom.xml. We have to execute the command mvn package, and this will generate the executable JAR file inside the target folder.

Using Spring Boot to Create JAR File

Spring Boot applications also provide the flexibility to create a JAR file without using the jar tool. Some configurations have to be made in the pom.xml file to generate an executable JAR file. The JAR file is generated with the help of the spring-boot-maven-plugin plugin. Initially, the packaging tag with the value jar is added to the pom.xml . Here’s the XML tag for that.

And the required plugin has to be specified under the build/plugins in pom.xml file. Here's the XML for that.

Now that we've added the relevant plugins and made changes to the pom.xml. We have to execute the following command

The above command will generate the executable JAR file inside the target folder. And executing the JAR file will invoke the main class in the spring application.

Conclusion

  • JAR file stands for Java ARchive file , which aggregates all the components of a Java application.
  • A JAR file is capable of storing .class files, .java files , metadata, and resources(if any)
  • JDK provides the jar.exe / jar tool for performing actions on a JAR file.
  • The jar tool provides options like c, t, u , and x for handling operations on a JAR file.
  • JAR files are executed by specifying the main class with the -cp argument or using a manifest file.
  • An executable JAR file is generated with maven and spring boot applications as well.

Explore more about such interesting topics in java from this informative thread over here.

JAR File Specification

In many cases, JAR files are not just simple archives of java classes files and/or resources. They are used as building blocks for applications and extensions. The META-INF directory, if it exists, is used to store package and extension configuration data, including security, versioning, extension and services.

The META-INF directory

  • MANIFEST.MF
  • INDEX.LIST
  • x.SF
  • x.DSA
  • services/

Name-Value pairs and Sections

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:

; Also: 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

The main section contains security and configuration information about the JAR file itself, as well as the application or extension that this JAR file is a part of. 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:

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

  • 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 extensions or libraries that this application or extension needs. URLs are separated by one or more spaces. The application or extension class loader uses the value of this attribute to construct its internal search path. See the Class-Path Attribute section for details.
    • 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.
    • Extension-List: This attribute indicates the extensions that are needed by the applet. Each extension listed in this attribute will have a set of additional attributes that the applet uses to specify which version and vendor of the extension it requires.
    • <extension>-Extension-Name: This attribute is the unique name of the extension. The Java Plug-in will compare the value of this attribute with the Extension-Name attribute in the manifests of installed extensions to determine if the extension is installed.
    • <extension>-Specification-Version: This attribute specifies the minimum extension specification version that is required by the applet. The Java Plug-in will compare the value of this attribute with the Specification-Version attribute of the installed extension to determine if the extension is up to date.
    • <extension>-Implementation-Version: This attritute specifies the minimum extension implementation version number that is required by the applet. The Java Plug-in will compare the value of this attribute with the Implementation-Version attribute of the installed extension to see if a more recent implementation needs to be downloaded.
    • <extension>-Implementation-Vendor-Id: This attribute can be used to identify the vendor of an extension implementation if the applet requires an implementation from a specific vendor. The Java Plug-in will compare the value of this attribute with the Implementation-Vendor-Id attribute of the installed extension.
    • <extension>-Implementation-URL: This attribute specifies a URL that can be used to obtain the most recent version of the extension if the required version is not already installed.
    • Extension-Name: This attribute specifies a name for the extension contained in the Jar file. The name should be a unique identifier such as the name of the main package comprising the extension.
    • 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.
    • Implementation-Vendor-Id: Deprecated: This attribute may be ignored in a future release. The value is a string id that uniquely defines the organization that maintains the extension implementation.
    • Implementation-URL: Deprecated: This attribute may be ignored in a future release. This attribute defines the URL from which the extension implementation can be downloaded from.
    • 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.

    Per-Entry Attributes

    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.
      • 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.
      • 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

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

      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-INF directory: 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

      • 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.

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

      Signature Validation

      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.

      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.

      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:

      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.

      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.

      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:

      The corresponding signature file would be:

      The Magic Attribute

      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:

      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

      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)

      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

      • 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).
        • 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.
        • 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.
        • 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.
        • 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).
        • If a file cannot be parsed according to this spec, a warning should be output, and none of the signatures should be trusted.
        • 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.
        • 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.
        • No digest or signature algorithms are mandated or restricted by this standard.
        • At least one digest algorithm must be supported.
        • If the digest algorithm, signature algorithm, or keysize is restricted by the jdk.jar.disabledAlgorithms security property, the JAR will be treated as unsigned. Note that the jdk.jar.disabledAlgorithms security property is currently used by the JDK Reference implementation. It is not guaranteed to be examined and used by other implementations.

        JAR Index

        Overview

        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 InvalidJarIndexException 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 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

        Service Provider

        Overview

        Files in the META-INF/services directory are service provider configuration files. A service is a well-known set of interfaces and (usually abstract) classes. A service provider is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself. Service providers may be installed in an implementation of the Java platform in the form of extensions, that is, jar files placed into any of the usual extension directories. Providers may also be made available by adding them to the applet or application class path or by some other platform-specific means.

        A service is represented by an abstract class. A provider of a given service contains one or more concrete classes that extend this service class with data and code specific to the provider. This provider class will typically not be the entire provider itself but rather a proxy that contains enough information to decide whether the provider is able to satisfy a particular request together with code that can create the actual provider on demand. The details of provider classes tend to be highly service-specific; no single class or interface could possibly unify them, so no such class has been defined. The only requirement enforced here is that provider classes must have a zero-argument constructor so that they may be instantiated during lookup.

        Provider-Configuration File

        A service provider identifies itself by placing a provider-configuration file in the resource directory META-INF/services. The file’s name should consist of the fully-qualified name of the abstract service class. The file should contain a newline-separated list of unique concrete provider-class names. Space and tab characters, as well as blank lines, are ignored. The comment character is ‘#’ (0x23); on each line all characters following the first comment character are ignored. The file must be encoded in UTF-8.

        Example

        • public abstract CharEncoder getEncoder(String encodingName);
        • public abstract CharDecoder getDecoder(String encodingName);

        Each method returns an appropriate object or null if it cannot translate the given encoding. Typical CharCodec providers will support more than one encoding.

        If sun.io.StandardCodec is a provider of the CharCodec service then its jar file would contain the file META-INF/services/java.io.spi.CharCodec. This file would contain the single line:

        To locate an encoder for a given encoding name, the internal I/O code would do something like this:

        The provider-lookup mechanism always executes in the security context of the caller. Trusted system code should typically invoke the methods in this class from within a privileged security context.

        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 requires. These relative URLs are treated relative to the code base from which the containing application was loaded.

        An application (or, more generally, a JAR file) specifies the relative URLs of the libraries that it requires with 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 a slash ( / ) are assumed to refer to JAR files. For example:

        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 from which the containing application or library was loaded. 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:

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

        As a result, the resulting application class path would be the following:

        If x.jar had dependencies of its own, then these would be added according to the same rules for each subsequent URL. In the actual implementation, JAR file dependencies are processed lazily so that the JAR files are not 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 through the manifest attribute, Sealed , whose value is true or false (case irrelevant). For example:

        This 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, then 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:

        This 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.

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

        JAR File Format

        Java_Zero_to_100

        JAR (Java Archive) is a file format based on the ZIP file format.

        It is used to bundle resources, class files, sound files, images, etc. for a Java application or applet. It also provides data compression.

        A JAR file as a special kind of a ZIP file. You can digitally sign the contents of a JAR file to provide security. It provides a platform-independent file format.

        You can use the JAR API to manipulate a JAR file in a Java program.

        A JAR file can have an optional META-INF directory to contain files and directories containing information about application configuration.

        META-INF directory

        The following table lists the entries in a META-INF directory.

        Jar tools

        The JDK ships a jar tool to create and manipulate JAR files. You can also create and manipulate a JAR file using the Java API using classes in the java.util.jar package.

        The JAR API has some new classes to deal with a manifest file. The Manifest class represents a manifest file.

        To create a JAR file using the jar tool, many command-line options are available.

        The following code lists the command-line options for the jar tool.

        Creating a JAR File

        Use the following command to create a test.jar JAR file with two class files called A.class and B.class:

        In the above command, the option c indicates that we are creating a new JAR file and the option f indicates that we are specifying a JAR file name, which is test.jar.

        At the end of the command, we can specify one or more file names or directory names to include in the JAR file.

        To view the contents of the test.jar file, execute the following command:

        The option t indicates that we are interested in the table of contents of a JAR file.

        The option f indicates that we are specifying the JAR file name, which is test.jar in this case.

        The above command will generate the following output:

        jar command had automatically created two extra things for you: one directory called META-INF and a file named MANIFEST.MF in the META-INF directory.

        The following command will create a test.jar file by including everything in the current working directory.

        The following command will create a JAR file with all class files in the book/archives directory and all images from the book/images directory.

        We can specify a manifest file using the command-line option while creating a JAR file.

        The manifest file is a text file that contains all manifest entries for your JAR file.

        The manifest file must have a blank line at the end of the file. Otherwise, the last entry in the manifest file will not be processed.

        The following command will use a manifest.txt file while creating test.jar file including all files and sub-directories in the current directory.

        The order of the options used in the above command matters. f occurs before m, we must specify the JAR file name, test.jar, before the manifest file name manifest.txt.

        You can rewrite the above command as follows:

        Updating a JAR File

        Use the option u to update an existing JAR file entries or its manifest file.

        The following command will add a C.class file to an existing test.jar file:

        Suppose we have a test.jar file and we want to change the Main-Class entry in its manifest file to HelloWorld class. You can do that by using the following command:

        In this command, the option u indicates that we are updating a JAR file; the option f indicates that we are specifying the JAR file name, which is test.jar, and the option e indicates that we are specifying the Main-Class entry’s value as HelloWorld for the MANIFEST.MF file in test.jar file.

        Indexing a JAR File

        We can generate an index file for JAR file. It is used to speed up class loading.

        We must use the option i with the jar command in a separate command, after creating a JAR file.

        This command will add a META-INF/INDEX.LIST file to the test.jar file. We can verify it by listing the table of contents of the test.jar file by using the following command:

        Extracting a JAR File

        To extract all or some entries from a JAR file, use the option x with the jar command.

        To extract all entries from a test.jar file

        The option x extracts the entries from the JAR file.

        The option f specifies the file name, which is test.jar.

        The above command will extract all entries from test.jar file in the current working directory.

        It will create the same directory structure as it exists in the test.jar file.

        To extract individual entries from a JAR file, list them at the end of the command. The entries should be separated by a space.

        The following command will extract A.class and book/HelloWorld.class entries from a test.jar file:

        To extract all class files from a book directory, you can use the following command:

        Listing JAR File Contents

        Use the option t with the jar command to list the table of contents of a JAR file on the standard output.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *