Introduction to the

Java programmers are either creating JARs every day or on their way to creating JARs, and various dependency references are presented in the form of JARs. But with the advent of modern IDEs, I think many programmers have largely stopped dealing directly with JARs.

In other words, they no longer recognize the JAR package.

So what exactly is a JAR package? What are its secrets? Let’s take a look.

What exactly is a JAR package

A JAR is a ZIP file, so you can actually create or unzip a JAR using ZIP-related commands.

The difference is that there is a META-INF folder in the JAR package. Through this folder, the JAR package can perform more operations.

JDK also comes with a jar command, through the jar command to create and update the operation of the jar package, the following is the description of the jar command:

Since the concept of modularity was introduced after JDK9, there have been significant changes to jar commands since JDK9:

Let’s look at the use of the jar command in JDK14:

This isn’t primarily about jar commands, so we won’t expand on them.

Meta-inf directory

The main difference between JAR and ZIP is that the JAR contains the META-INF directory (which is not required). Let’s look at the structure of a more commonly used lombok.jar:

This version is relatively new, so it uses the latest JPMS notation. You can see that there is a module-info.class file under the root of the JAR, indicating that the JAR is modularized.

Then take a look at the META-INF directory, which contains a MANIFEST.MF file:

Manifest-version: 1.0 Ant Version: Apache Ant 1.7.1 Created-By: 14.3-B01-101 (Apple Inc.) Premain-class: lombok.launch.Agent Agent-Class: lombok.launch.Agent Can-Redefine-Classes: true Main-Class: Lombok. Launch. The Main lombok - Version: 1.18.10

Manifest. MF is used to define packation-related data. Here we can see Lombok’s Manifest. MF file defines the Manifest version number, creation time, version number, and several types of classes.

The Services folder contains the services that can be offered.

The files listed here are not exhaustive, there are actually several types of files:

  • INDEX.LIST

-i is a class index file that can be used to speed up the loading of a class.

  • x.SF

The signature file for the JAR package.

  • x.DSA

A signature block file associated with a signature file that has the same base file name. This file stores the digital signature of the corresponding signed file.

  • versions/

It is intended for use with multi-version features, where different versions of classes and resources are stored.

For example, the following command creates a JAR package for multiple distributions and places some files in the META-INF/versions/9 directory.

 jar --create --file mr.jar -C foo classes --release 9 -C foo9 classes

module-info.class

If we were using JPMS modularization after JDK9, we would have generated this module-info.class. The main purpose of this file is to describe the direct relationship between the module and the external module.

Take a look at Lombok’s example:

module lombok {
    requires java.compiler;
    requires java.instrument;
    requires jdk.unsupported;
    requires static org.mapstruct.processor;

    exports lombok;
    exports lombok.experimental;
    exports lombok.extern.apachecommons;
    exports lombok.extern.java;
    exports lombok.extern.jbosslog;
    exports lombok.extern.log4j;
    exports lombok.extern.slf4j;
    exports lombok.extern.flogger;

    provides javax.annotation.processing.Processor with lombok.launch.AnnotationProcessorHider$AnnotationProcessor;
    provides org.mapstruct.ap.spi.AstModifyingAnnotationProcessor with lombok.launch.AnnotationProcessorHider$AstModificationNotifier;
}

Here we define the dependent classes and service providers, as well as the classes we provide to others.

After JDK9, there are two paths, the former Class Path and the Module Path. Modular Jar is a Modular Jar when it is deployed in the module path. When it is deployed in Class Path, it is a non-modular JAR.

Similarly, if a non-modular JAR is defined in the module path, then the non-modular JAR is automatically converted into an automatic module.

If the JAR package defines an automatic-module-name in its MANIFEST.MF, then the Module Name is this value; otherwise, the Module is defined from the JAR Name.

Automatic module is mainly produced for downward compatibility.

For more information on JPMS, see my previous article: A New JDK9 Feature :JPMS Modularity.

versions

Versions are mainly used with multi-release JARs:

Multi-Release: true

Multi-release JAR means that a JAR package can support different versions of the JDK. We can specify the class files or properties files that different versions of the JDK depend on as needed. This feature is still very helpful when we are doing JDK upgrades.

In general, the directory structure looks like this: META-INF/versions/N

Where N represents the major releases of the JDK, such as 9,10,11, and so on.

The class loader will first load the required classes in the META-INF/versions/N directory, then load the required classes in the lower versions of META-INF/versions/N directory, and finally load the additional class files in the root directory of META-INF/.

The MANIFEST. MF, rounding

Manifest. MF stores configuration information in key: value format, which can be divided into two parts: main-section information and individual-section information.

Let’s take a simple example:

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

Among them

Manifest-Version: 1.0
Created-By: 1.8 (Oracle Inc.)
Sealed: true

This is the main-section information. Let’s use a diagram to see what main-section information is:

The main-section information can be followed by a Name: Value to enable independent entry-specific Attributes configuration:

Name: foo/bar/
Sealed: false

For example, the Sealed property above is specific to the package foo/bar/, and its Sealed property is set to false.

In addition to package versioning and sealing information, you can also define Content-Type, Java-Bean, X-Digest-Y, and Magic Attributes.

The JAR package signed

JAR packages can be signed using Jarsigner. The files associated with the signature are:

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

The signed JAR is the same as the original JAR, except that there are two more files in the META-INF/ folder: the signature file and the signature block file.

Signature file

The Signature file ends in.sf, which is similar to MANIFEST.MF in that you can specify signature-version and create-by.

In addition, you can specify security-related properties:

  • X – Digest – Manifest – the Main – the Attributes: where x is the Java security. The MessageDigest specified in the algorithm, the Main properties of the said.
  • X-Digest-Manifest: Represents a summary of the entire Manifest.

These two properties are mainly used to verify signatures.

Here’s an example:

If our manifest looks like this:

Class1. Class SHA-256-Digest: 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 should look like this:

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)

Summary of the signature file

If you digest the.sf file again, you get a digest of the signed file:

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

Sealed

We have a Sealed property:

Name: javax/servlet/internal/
Sealed: true

This property means that all classes in the javax/servlet/internal/ package must be loaded from this JAR.

This property is primarily for the security of the JAR package.

This article is included in

一文读懂jar包的小秘密

The most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the tips to wait for you to discover!

Welcome to pay attention to my public number: “procedures those things”, understand technology, more understand you!