Publishing a Java function in function computation (Aliyun FC) often requires packaging the function into a zip package or jar package of all-in-one. This technology 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 dependencies. All dependencies except the Java virtual machine are embedded in the Jar package. We know that Java’s dependencies are divided into two types: scattered. class files and jar files packaged in zip format. FatJar is an all-in-one Jar package. FatJar technology allows those Jars for final release to be deployed and run easily.
Three Packing Methods
We know that. java source files are compiled into bytecode. class files by the compiler. The Java virtual machine executes the. class file. A Java program can have many. class files. These. class files can be loaded into memory by the class loader run-time of the Java virtual machine. The Java virtual machine can load all. class files from a directory, but these scattered. class files are not easy to distribute. All Java supports packing fragmented. class files into ZIP format. jar files, and class loaders of virtual machines support loading. jar files directly.
A normal Java program consists of several. class files and jar files of the dependent third party library.
- Unshaded method
Non-occlusion is relative to occlusion, which can be understood as a simple method. Unzip all the jar files and repackage them into a new separate jar file.
Maven Assembly Plugin makes it easy to package non-masking methods.
Maven Assembly Plugin
Maven Assembly Plugin is a packaging aggregation plug-in. Its main function is to package the compilation and output of the project into a separate release package, which includes modules, documents and other files. Use descriptors to configure the combinations of materials that need to be packaged. Common descriptors are predefined for direct use.
The predefined descriptors are as follows
Bin only packages the compiled results and contains README, LICENSE and NOTICE files. The output file formats are tar.gz, tar.bz2 and zip.
* jar-with-dependencies packages the compiled results with all the dependencies, and if the dependencies are jar packages, the jar packages will be unzipped and tiled into the final uber-jar. The output format is jar.
* SRC packages 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 are packaged. The output formats are tar.gz, tar.bz2 and zip.
In addition to predefined descriptors, users can also specify descriptors to meet different packaging requirements.
Packaging into uber-jar requires the use of predefined jar-with-dependencies descriptors:
Add the following configuration to pom. XML
Gradle Java plugin
Gradle packages a non-masked jar package, many plug-ins can be used, but because of gradle’s flexibility, it can be directly implemented with groove’s dsl.
The non-masking method extracts all the files in the jar package into a directory and then packages them in the same fatjar. For complex applications, it is likely to encounter the problem of mutual coverage of homonymous classes.
The masking method modifies the classpath in the dependent package to a subpath, which can avoid the problem of overlapping the same-name classes to some extent. The eventual release of the jar will not bring the delivery dependency conflict problem downstream.
Maven Shade Plugin
Add the following configuration to pom. XML
Gradle Shadow plugin
Gradle shadow plugin is very simple to use and can take effect after simply declaring the plug-in.
The masking method relies on modifying the bytecode of the class and updating the package path of the dependent file to avoid the conflict of the same-name and same-package classes, but the renaming also brings other problems, such as the use of the code.
Class. forName or ClassLoader. loadClass loaded class, Shade Plugin
It’s not perceptible. For example, META-INF/services/javax.script.ScriptEngineFactory does not belong to class files, but it will have problems after being overwritten.
- Nested method (Jar of Jars)
Another way is to nest other jars in the jar package, which completely avoids the problem of decompressing the same name coverage, but this method is not supported by JVM native, because the ClassLoader provided by JDK only supports class files that load nested jar packages. So this approach requires custom ClassLoader to support nested jars.
Onejar Maven Plugin
One-JAR is a tool based on the above nested jar implementation. Onejar-maven-plugin is a community-based Maven plug-in implemented by onejar.
Spring boot plugin
One-JAR is a bit out of repair and has not been maintained for a long time. Maven Plugin provided by Spring Boot can also package Fatjar, support non-masked and nested hybrid mode, and support Maven and gradle.
The requiresUnpack parameter can customize those jars that do not want to be decompressed and pack them into Fatjar in a nested way.
The internal structure of the package is as follows
Application class files are placed in the BOOT-INF/classes directory, and dependent packages are placed in the BOOT-INF/lib directory.
View the META-INF/MANIFEST.MF file, which contains
The startup class is a fixed org. spring framework. boot. loader. JarLauncher, and the entry class of the application needs to be configured as Start-Class. The main purpose of this is to support class loading of nested jar packages and replace the default lassLoader.
But the jar package needed for function computing Java Runtime is a packaging structure, which will be decompressed when the server runs. The. / lib directory is added to the classpath, and Main-Class will not be invoked alone. So custom ClassLoader is not valid, so don’t use nested jar structures unless you redefine ClassLoader or classpath to support customized class paths such as BOOT-INF/classes and BOOT-INF/lib in the entry function specify.
From the perspective of Fatjar alone, Spring boot maven/gradle is the most elaborate. However, the custom paths inside the jar package are not compatible with function calculation after decompression. So if it is used for function computing packaging, it is recommended to use Unshaded or Shared packaging, but you need to pay attention to file coverage.
Author of this article: Relying on virtue
Read the original text
This article is the original content of Yunqi Community, which can not be reproduced without permission.