什么是胖罐子?

我听到有人说他们创建了一个胖的 JAR 并部署它,这到底是什么意思呢?

111246 次浏览

Fat jar 是 jar,它包含来自项目所依赖的所有库的类,当然还包括当前项目的类。

在不同的构建系统中,fat jar 的创建方式是不同的,例如,在 Gradle,人们可以使用(指示)来创建它:

task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.example.Main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}

在 Maven 中是这样做的(在设置了常规 jar 之后) :

<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>

<plugin>
<groupid>org.dstovall</groupid>
<artifactid>onejar-maven-plugin</artifactid>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<onejarversion>0.97</onejarversion>
<classifier>onejar</classifier>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>

Fat jar 或 uber jar 是一个 jar,它包含所有的项目类文件和资源,以及它的所有依赖项。达到这种效果有不同的方法:

  • 将依赖项的 jar 复制到 main jar 中,然后使用特殊的类装入器(onejar,spring-boot-plugin: repackage)装入
  • 依赖项的 jar 被提取到主 jar 层次结构的顶部(maven-Assembly-plugin 及其带依赖项的 jar 程序集)
  • 依赖项的 jar 在主 jar 层次结构的顶部被解压缩,并且它们的包被重命名(带有阴影目标的 maven-shadow-plugin)

下面示例组装插件配置 带依赖项的 jar:

<project>
...
<build>
...
<plugins>
<plugin>
<!-- NOTE: We don't need a groupId specification because the group is
org.apache.maven.plugins ...which is assumed by default.
-->
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<classifier
</configuration>
...
</project>

更详细的解释: Uber-JAR at imagej.net

在可执行 jar 的情况下,考虑胖 jar 的另一种方式是您可以通过调用:

java -jar myFatLibrary.jar

不需要 -cp/--classpath,甚至不需要双击 jar 图标。

胖 jar 仅仅包含与经典 jar + 类相同的类,它们来自所有的运行时依赖项。

使用 Jeka (https://jeka.dev) ,你可以通过编程实现:

JkPathTreeSet.of(Paths.get("classes")).andZips(
Paths.get("bouncycastle-pgp-152.jar"),
Paths.get("classgraph-4.8.41.jar"),
Paths.get("ivy-2.4.0.jar")
).zipTo(Paths.get("fat.jar"));

或者仅仅通过参数化 Java 插件:

javaPlugin.getProject().getMaker().defineMainArtifactAsFatJar(true);

不同的名字只是打包 java 应用程序的一种方式。

Skinny -仅包含您在代码编辑器中逐字输入的位,不包含任何其他内容。

-包含所有以上附加值,应用程序的直接依赖于您的应用程序(db 驱动程序,实用程序库等)。

-瘦的反面-只包含运行应用程序所需的位,但不包含应用程序本身。基本上是一个预先打包好的“应用服务器”,您可以在其中部署您的应用程序,与传统的 JavaEE 应用程序服务器风格相同,但有重要的区别。

Fat/Uber -包含你自己写的程序 还有的直接依赖程序 还有运行你的程序所需的比特。

资料来源: 来自 Dzone 的文章

Visual representation of JAR types

分级文件

在 Java 空间中,通常将 应用程序及其依赖项打包为单个分发归档文件中的单独 JAR。这种情况仍然会发生,但是现在有另一种常见的方法: 将依赖项的类和资源直接放到应用程序 JAR 中,创建所谓的 uber 或 fat JAR。

下面是 build.gradle文件中的 uberJar任务演示:

task uberJar(type: Jar) {
archiveClassifier = 'uber'


from sourceSets.main.output


dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}
}

在本例中,我们使用项目ーー configurations.runtimeClasspath.filesーー的运行时依赖项,并使用 zipTree()方法包装每个 JAR 文件。结果是一个 ZIP 文件树的集合,其内容与应用程序类一起复制到 uber JAR 中。