为应用程序及其依赖项创建 UberJAR

Java 应用程序的一个常见要求是可以通过复制单个文件来部署。对于仅依赖于标准 Java SE 类库的简单应用程序,通过创建包含所有(已编译)应用程序类的 JAR 文件来满足此要求。

如果应用程序依赖于第三方库,事情就不那么简单了。如果只是将依赖项 JAR 文件放在应用程序 JAR 中,标准 Java 类加载器将无法找到库类,并且你的应用程序将无法启动。相反,你需要创建一个包含应用程序类和相关资源以及依赖项类和资源的 JAR 文件。这些需要组织为单个命名空间以供类加载器搜索。

这样的 JAR 文件通常被称为 UberJAR。

使用 jar 命令创建 UberJAR

创建 UberJAR 的过程很简单。 (为简单起见,我将使用 Linux 命令。对于 Mac OS,命令应该是相同的,对于 Windows,命令应该是相同的。)

  1. 创建一个临时目录,并将目录更改为该目录。

    $ mkdir tempDir
    $ cd tempDir
    
  2. 对于每个从属 JAR 文件,按照它们需要在应用程序的类路径中出现的相反顺序,使用 jar 命令将 JAR 解压缩到临时目录中。

    $ jar -xf <path/to/file.jar>
    

    对多个 JAR 文件执行此操作将覆盖 JAR 的内容。

  3. 将应用程序类从构建树复制到临时目录中

    $ cp -r path/to/classes .
    
  4. 从临时目录的内容创建 UberJAR:

    $ jar -cf ../myApplication.jar
    

    如果要创建可执行 JAR 文件,请按此处所述包含适当的 MANIFEST.MF。

使用 Maven 创建 UberJAR

如果你的项目是使用 Maven 构建的,你可以使用“maven-assembly”或“maven-shade”插件创建 UberJAR。有关详细信息,请参阅 Maven Assembly 主题(在 Maven 文档中)。

UberJAR 的优点和缺点

UberJAR 的一些优点是不言而喻的:

  • UberJAR 很容易分发。
  • 你无法破坏 UberJAR 的库依赖关系,因为这些库是自包含的。

此外,如果使用适当的工具来创建 UberJAR,则可以选择排除未在 JAR 文件中使用的库类。但是,这通常通过类的静态分析来完成。如果你的应用程序使用反射,注释处理和类似技术,则需要注意不要错误地排除类。

UberJARs 也有一些缺点:

  • 如果你有许多具有相同依赖关系的 UberJAR,那么每个 UberJAR 都将包含依赖关系的副本。
  • 一些开源库有这些许可证可以排除 1 个 它们在 UberJAR 使用。

1 - 某些开源库许可证允许你仅使用库,最终用户可以将库的一个版本替换为另一个版本。UberJARs 可以很难替换版本依赖项。