Что такое толстый JAR?

Я слышал, как люди говорят, что они создают толстый JAR и разворачивают его. Что они на самом деле имеют в виду?

Ответ 1

Жирная фляга - это банка, содержащая классы из всех библиотек, от которых зависит ваш проект, и, конечно, классы текущего проекта.

В разных системах сборки жирный фрейм создается по-разному, например, в 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 это делается таким образом (после настройки обычной банки):

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

<!-- ... -->

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

Ответ 2

Fat jar или uber jar - это банка, содержащая все файлы и ресурсы класса проекта, упакованные вместе со всеми ее зависимостями. Существуют разные способы достижения такого эффекта:

  • Флажки
  • dependations копируются в основную банку, а затем загружаются с помощью специального загрузчика классов (onejar)
  • баги зависимостей извлекаются в верхней части главной иерархии jar (сборка maven-assembly-plugin с сборкой jar-with-dependencies, maven-shade-plugin с целью тени)

Ниже приведен пример конфигурации плагина сборки jar-with-dependencies:

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

Ответ 3

В случае исполняемого флага другой способ думать о толстой банке - это тот, который вы можете выполнить, вызвав:

java -jar myFatLibrary.jar

без необходимости -cp/--classpath или даже дважды щелкнуть значок баннера.

Ответ 4

Различные названия - это просто способы упаковки Java-приложений.

Тощий - содержит ТОЛЬКО биты, которые вы буквально вводите в редактор кода, и НИЧЕГО больше.

Тонкий - содержит все вышеперечисленное, а также прямые зависимости приложений от вашего приложения (драйверы БД, служебные библиотеки и т.д.).

Пустота - Инверсия тонкого - Содержит только биты, необходимые для запуска вашего приложения, но НЕ содержит самого приложения. По сути, это предварительно упакованный "сервер приложений", на котором вы можете позднее развернуть свое приложение в том же стиле, что и традиционные серверы приложений Java EE, но с существенными отличиями.

Fat/Uber - содержит бит, который вы буквально пишете себе, плюс прямые зависимости вашего приложения, плюс биты, необходимые для запуска вашего приложения "самостоятельно".

Источник: Статья из Dzone

Visual representation of JAR types

Ответ 5

Толстый 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);

Ответ 6

из документации Gradle

В пространстве Java приложения и их зависимости обычно упаковывались как отдельные JAR файлы в одном архиве распространения. Это все еще происходит, но есть и другой распространенный подход: размещение классов и ресурсов зависимостей непосредственно в JAR приложения, создание так называемого UAR или жирного JAR.

Вот демонстрация задачи uberJar в файле build.gradle:

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 - и упаковывали каждый из файлов JAR методом zipTree(). В результате получается коллекция файлов ZIP файлов, содержимое которых копируется в UAR JAR вместе с классами приложения.