跳转至内容

Java 包指南

来自 ArchWiki
Arch 软件包指南

32 位CLRCMake交叉编译DKMSEclipseElectron字体Free PascalGNOMEGoHaskellJavaKDE内核模块LispMesonMinGWNode.js非自由OCamlPerlPHPPythonRRubyRust - 安全ShellVCSWebWine

本文档定义了在 Arch Linux 上打包 Java 程序的拟议标准。Java 程序在没有依赖项重叠的情况下进行干净打包是出了名的困难。本文档描述了一种解决此问题的方法。这些指南非常灵活,能够涵盖处理 Java 应用程序时出现的各种不同情况。

简介

Arch Linux 的打包人员似乎无法就如何处理 Java 包达成一致。在官方和非官方存储库以及 AURPKGBUILD 中使用了各种方法。这些解决方案包括将所有东西放在 /opt 目录中,并在 /usr/bin 中放置 shell 脚本,或者将配置文件放在 /etc/profile 中。另一些则放在 /usr/share 的目录中,并在 /usr/bin 中放置脚本。许多人向系统的 CLASSPATHPATH 添加了不必要的文件。

典型的 Java 应用程序结构

大多数桌面 Java 应用程序都具有相似的结构。它们通常通过独立于系统的(但依赖于包!)安装程序进行安装。这通常会将所有内容安装在一个目录中,其中包含名为 binlibjarconf 等的子目录。通常会有一个主 jar 文件,其中包含主要的执行类。通常会提供一个 shell 脚本来运行主类,这样用户就不必直接调用 Java 解释器。这个 shell 脚本通常相当复杂,因为它跨发行版通用,并且经常包含针对不同系统的特殊情况(例如 Cygwin)。

lib 目录通常包含满足 Java 应用程序依赖项的捆绑 jar 文件。这使得用户可以轻松安装程序(包含所有依赖项),但却让打包开发人员头疼不已。当多个包捆绑相同的依赖项时,就会浪费空间。过去,当桌面 Java 应用程序和库较少时,这并不是一个大问题,而且现有的应用程序和库往往都非常大。现在情况不同了……

运行程序所需Calculating other files are usually stored in the same folder as the main jar file, or a subdirectory thereof. Since Java programs do not know where their classes were loaded from, they usually need to be run from within this directory (i.e. the shell script should cd into the directory), or an environment variable is set to indicate the directory's location.

Arch Linux 上的 Java 打包

在 Arch 上打包 Java 应用程序需要打包人员付出比现在多得多的努力。然而,这种努力是值得的,它将带来更干净的文件系统和更少的捆绑依赖项(随着越来越多的 Java 库被重构为自己的包,打包将变得更容易)。创建 Arch Linux Java 包时应遵循以下指南。

  • 如果 Java 库具有通用名称,则包名应以 java- 前缀开头,以帮助区分其他库。对于唯一命名的包(如 JUnit)、最终用户程序(如 Eclipse)或可以用其他前缀唯一描述的库(如 jakarta-commons-collections 或 apache-ant),则不需要这样做。
  • 将程序分发的 JAR 文件(并且仅 JAR 文件)放在 /usr/share/java/myprogram 目录中。这包括应用程序分发的任何依赖项 JAR 文件。但是,应努力将通用或大型依赖库放入其自己的包中。这只有在程序不依赖于特定版本的依赖库时才有可能。
此规则使得迭代重构依赖项成为可能。也就是说,最初可以将包及其所有依赖项放在一个目录中。测试完成后,可以一次重构一个主要依赖项。请注意,某些应用程序包含主 JAR 文件中的捆绑依赖项。也就是说,它们会将捆绑的依赖项解压并包含在主 JAR 文件中。这类依赖项通常非常小,重构它们的意义不大。
  • 如果程序供用户运行,请编写一个自定义 shell 脚本来运行主 JAR 文件。此脚本应放在 /usr/bin 中。库通常不需要 shell 脚本。请从头开始编写 shell 脚本,而不是使用程序中捆绑的脚本。删除测试自定义环境(如 Cygwin)的代码,以及试图确定 JAVA_HOME 是否已设置的代码(Arch 不使用 JAVA_HOME,它使用 archlinux-java 来设置 /usr/bin/java 的符号链接)。
对于 JAR 文件,这样的脚本应该如下所示:
#!/bin/sh
exec /usr/bin/java -jar '/usr/share/java/myprogram/myprogram.jar' "$@"
对于单个类文件,脚本应该如下所示:
#!/bin/sh
exec /usr/bin/java '/usr/share/java/myprogram/myprogramclassname' "$@"
  • 除非有明确的原因不这样做(即,CLASSPATH 用作插件机制),否则使用 Java 解释器的 -cp 选项设置 CLASSPATHCLASSPATH 应包含 /usr/share/java/myprogram 目录中的所有 JAR 文件,以及已重构到其他目录的依赖库中的 JAR 文件。您可以使用类似以下代码的内容:
for name in /usr/share/java/myprogram/*.jar ; do
  CP=$CP:$name
done
CP=$CP:/usr/share/java/dep1/dep1.jar
java -cp $CP myprogram.java.MainClass
  • 确保 shell 脚本是可执行的!
  • 包分发的其他文件应存储在 /usr/share 下的一个以包命名的目录中。您可能需要在 shell 脚本中将此目录的位置设置为一个变量,例如 MYPROJECT_HOME。此指南假定程序期望所有文件都在同一目录中(这是 Java 包的标准)。如果将配置文件放在别处(例如,日志放在 /var/log)似乎更自然,请随时这样做。
请注意,在某些系统上,/usr 可能以只读方式挂载。如果共享目录中有应用程序需要写入的文件,可能需要将它们移至 /etc/var 或用户的家目录。
  • 与 Arch Linux 包的标准一样,如果无法在不进行大量工作的情况下遵守上述标准,则应按照其首选方式安装包,并将生成的目录放置在 /opt 中。这对于捆绑 JRE、包含定制版本依赖项或执行其他奇怪或繁琐任务的程序很有用。

多个 API 实现

如果您的包分发了常用的 API 实现(例如 JDBC 驱动程序),您应该将库放在 /usr/share/java/apiname 下。这样,允许用户从各种实现中选择的应用程序就会知道去哪里查找它们。仅将此位置用于原始库包。如果此类实现是应用程序发行版的一部分,**不要**将其 JAR 文件放在公共位置,而是使用普通的包结构。

示例目录结构

为了清楚起见,这里有一个假设名为 foo 的程序的示例目录结构。由于 foo 是一个通用名称,因此包名为 java-foo,但请注意这不会反映在目录结构中。

  • /usr/share/java/foo/
  • /usr/share/java/foo/foo.jar
  • /usr/share/java/foo/bar.jarjava-foo 的包含的依赖项)
  • /usr/share/foo/
  • /usr/share/foo/*.*java-foo 需要的一些通用文件)
  • /usr/bin/foo(可执行 shell 脚本)

依赖

Java 包可以根据它们的需求指定 java-runtimejava-environment 作为依赖项。对于大多数包,java-runtime(Java 运行时环境)是运行用 Java 编写的软件所必需的。java-environment(Java 开发工具包)是需要编译 Java 源代码为字节码的包所必需的。

有关更多信息,请参阅 Java

© . This site is unofficial and not affiliated with Arch Linux.

Content is available under GNU Free Documentation License 1.3 or later unless otherwise noted.