Ali Java Architect Packaging Fatjar method summary

Source: Internet
Author: User
Tags maven shade plugin

When you publish a Java function in function calculation (Aliyun FC), you often need to package the function into a all-in-one zip package or jar package. This technique of packaging all-in-one in Java is often called Fatjar technology. This article summarizes several methods of packaging Fatjar in Java.

What is Fatjar

Fatjar, also known as Uber-jar, is a Jar package that contains all the dependencies. All dependencies except Java virtual machines are embedded in the Jar package. We know that Java dependencies are divided into two types, fragmented. class files, and a jar file packaged in a ZIP format for multiple. class files. Fatjar is a all-in-one Jar package. Fatjar technology allows those jars for final release to be easily deployed and run.

Three ways to pack

We know that. Java source code files are compiled into bytecode. class files by the compiler. The Java virtual machine executes a. class file. A Java program can have a number of. class files. These. class files can be loaded into memory by the class loader runtime of the Java Virtual machine. Java virtual machines can load all. class files from a directory, but these fragmented. class files are not easy to distribute. All Java support Packages a fragmented. class file into a. jar file in a zip format, and the class loader for the virtual machine supports loading. jar files directly.

A normal Java program consists of several. class files and jar files that depend on the third-party libraries.

1. Non-masking method (unshaded)

The non-shadowing is relative to the shadowing and can be understood as a simple method. Unzip all the jar files and repackage them into a new separate jar file.

The Maven Assembly Plugin makes it easy to package non-masking methods.

Maven Assembly Plugin

Maven Assembly Plugin is a packaged aggregation plugin whose main function is to bundle the compilation output of a project together, modules, documents, and other files into a separate release package. Use the descriptor (descriptor) to configure the combination of items that need to be packaged. and predefined descriptors are used for direct use.

The predefined descriptors are as follows

Bin only packages the compiled results and contains the README, LICENSE and NOTICE files, the output file format is tar.gz, tar.bz2 and zip.
Jar-with-dependencies packages The compiled results and takes all the dependencies, if the jar package is dependent, the jar will be unpacked and tiled into the final uber-jar. The output format is jar.
SRC Packaging source files. The output formats are tar.gz, tar.bz2, and zip.
Project packages the entire project, and all files and directories except the deployment output directory target will be packaged. The output formats are tar.gz, tar.bz2, and zip.
In addition to predefined descriptors, users can specify descriptors to meet different packaging requirements.

To package into Uber-jar, you need to use a predefined jar-with-dependencies descriptor:

Add the following configuration to the Pom.xml

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-assembly-plugin</artifactId>

<version>choose LATEST version here</version>

<configuration>

<descriptorRefs>

<descriptorRef>jar-with-dependencies</descriptorRef>

</descriptorRefs>

</configuration>

<executions>

<execution>

<id>assemble-all</id>

<phase>package</phase>

<goals>

<goal>single</goal>

</goals>

</execution>

</executions>

</plugin>

Gradle Java Plugin

Gradle Package A non-shielded jar package, there are many plug-ins can be used, but because of the flexibility of gradle, can be directly implemented with Groove DSL.

Apply plugin: ' java '

Jar {

from {

(configurations.runtime). Collect {

It.isdirectory ()? It:ziptree (IT)

}

}

}

The non-shadowing method extracts all the files in the jar package into a directory and then packages the same fatjar. For complex applications, it is possible to encounter a class with the same name covering problems.

2. Masking method (Shaded)

The masking method modifies the classpath of the dependent package to a sub-path, which avoids the problem of overwriting the same class with the same name to some extent. The final released Jar will not be brought into the downstream of the transitive dependency conflict problem.

Maven Shade Plugin

Add the following configuration to the Pom.xml

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-shade-plugin</artifactId>

<version>3.1.1</version>

<configuration>

<!--put your configurations here--

</configuration>

<executions>

<execution>

<phase>package</phase>

<goals>

<goal>shade</goal>

</goals>

</execution>

</executions>

</plugin>

Gradle Shadow Plugin

Gradle Shadow plugin is very simple to use, simply declare the plugin to take effect.

Plugins {

Id ' com.github.johnrengelman.shadow ' version ' 2.0.4 '

Id ' Java '

}

Shadowjar {

Include ' *.jar '

Include ' *.properties '

Exclude ' a2.properties '

}

The masking method relies on modifying the class's bytecode, updating the packet path of the dependent file to avoid the same name as the same packet class conflict, but renaming also brings other problems, such as the use of Class.forName or Classloader.loadclass loaded classes in code, Shade The Plugin is not perceptible. File overwrite issues with the same name can not be eliminated, such as Meta-inf/services/javax.script.scriptenginefactory does not belong to the class file, but the problem occurs after being overwritten.

3. Nested methods (Jar of Jars)

Another way to do this is to nest other jars in the jar package, which avoids the problem of extracting overwriting with the same name, but this method is not supported by the JVM, because the ClassLoader provided by the JDK supports only the class file that loads the nested jar package. So this approach requires custom ClassLoader to support nested jars.

Onejar Maven Plugin

One-jar is a tool based on the nested JAR implementation above. Onejar-maven-plugin is a MAVEN plugin for community-based Onejar implementations.

<plugin>

<groupId>com.jolira</groupId>

<artifactId>onejar-maven-plugin</artifactId>

<version>1.4.4</version>

<executions>

<execution>

<goals>

<goal>one-jar</goal>

</goals>

</execution>

</executions>

</plugin>

Spring Boot Plugin

One-jar a bit of disrepair, long time no maintenance, Spring Boot provides maven Plugin can also be packaged Fatjar, support non-shadowing and nested mixed mode, and support Maven and Gradle.

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<layout>ZIP</layout>

<requiresUnpack>

<dependency>

<groupId>org.jruby</groupId>

<artifactId>jruby-complete</artifactId>

</dependency>

</requiresUnpack>

</configuration>

</plugin>

Plugins {

Id ' org.springframework.boot ' version ' 2.0.4.RELEASE '

}

Bootjar {

Requiresunpack ' */jruby-complete-. Jar '

}

The Requiresunpack parameter can be customized for those jars that do not want to be decompressed and packaged in a nested way inside the Fatjar.

Its packaged internal structure is

Example.jar

|

+-meta-inf

| +-manifest. Mf

+-org

| +-springframework

| +-boot

| +-loader

| +-<spring boot loader classes>

+-boot-inf

+-classes

| +-mycompany

| +-project

| +-yourclasses.class

+-lib

+-dependency1.jar

+-dependency2.jar

The applied class files are placed into the boot-inf/classes directory, and the dependent packages are placed into the Boot-inf/lib directory.

View Meta-inf/manifest. MF file with the contents of

Main-class:org.springframework.boot.loader.jarlauncher

Start-class:com.mycompany.project.myapplication

The startup class is a fixed org.springframework.boot.loader.JarLauncher, and the application's ingress class needs to be configured as Start-class. This is done primarily to support class loading of nested jar packages, replacing the default ClassLoader.

But the function calculates the Java runtime needs the jar package is one kind of packing structure, when the service side runs the decompression opens, the./lib directory is added to the classpath, and the main-class is not called alone. So the custom ClassLoader is not valid, so do not use nested JAR structures unless you specify in the Ingress function to redefine ClassLoader or classpath to support the customization of boot-inf/classes and Boot-inf/lib The class path.

Summary

From the Fatjar point of view, Spring boot Maven/gradle is the most refined. However, the custom path inside the jar package is not compatible with the function calculation after decompression. So if you are packing for function calculations, it is recommended to use unshaded or Shared packaging, but you need to be aware of file coverage issues.

Write at the end: Welcome message discussion, add attention, continuous UPDATE!!!

Ali Java Architect Packaging Fatjar method summary

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.