Java 打包準則

出自 Arch Linux 中文维基
(重新導向自Java package guidelines
Arch 打包準則

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

本文檔定義了 Arch Linux 下打包 Java 程序的建議標準。Java 程序是出了名的難以在沒有重疊的依賴關係的情況下乾淨利落地打包。本文檔描述了一種處理這種情況的方法。這些指南十分靈活,以涵蓋處理 Java 程序時遇到的許多不同情況。

介紹[編輯 | 編輯原始碼]

Arch Linux 的打包人員似乎無法就如何處理 Java 包達成一致。官方和非官方軟件庫以及 AURPKGBUILD 中使用了各種方法。這包括把所有東西扔到 /opt 裡,把 Shell 腳本放在 /usr/bin 或把配置文件放在 /etc/profile 中。其他的則是放在 /usr/share 目錄中,腳本放在 /usr/bin 中。許多做法在系統 CLASSPATHPATH 中添加了不必要的文件。

典型 Java 應用程式的結構[編輯 | 編輯原始碼]

大多數桌面 Java 應用程式結構類似。它們是由一個不依賴系統(但依賴軟件包!)的安裝程序安裝的。這通常會把所有東西都安裝在包含 binlibjarconf等子目錄的目錄下。一般會有一個包含主要可執行類的主 jar 文件。通常還會提供一個 Shell 腳本來運行主類,這樣用戶就不必直接調用 Java 解釋器。這個 Shell 腳本通常相當複雜,因為它需要在不同的發行版中通用,而且經常包括不同系統的特殊情況(例如 Cygwin)。

lib 目錄通常包含捆綁的 jar 文件來滿足 Java 程序的依賴。這使用戶安裝程序變得簡單(其中包含了所有依賴),但卻是軟件包開發者的噩夢。幾個軟件包捆綁相同的依賴會浪費空間。這在過去並不是一個大問題,當時桌面 Java 應用程式和庫較少,而那些存在的應用程式和庫本身往往也非常大。但現在情況不同了……

運行程序所需的其他文件通常與主 jar 文件存放在同一目錄或其子目錄下。由於 Java 程序不知道它們的類是從哪裏加載的,所以通常需要在這個目錄中運行(即 Shell 腳本應 cd 進入該目錄),或者設置一個環境變量來指示這個目錄的位置。

在 Arch Linux 中打 Java 包[編輯 | 編輯原始碼]

在 Arch 中打包 Java 應用程式將會比現在更費勁。然而,這是值得的,它可以使文件系統更乾淨,捆綁的依賴更少(隨着越來越多的Java 庫被重構為單獨的包,打包會變得更容易)。在創建 Arch Linux Java 包時,應遵循以下準則:

  • 如果 Java 庫有一個通用的名字,那麼包的名字應該在前面加上 java- 以與其他庫區分。對於命名獨特的包(如 JUnit)、終端用戶程序(如 Eclipse)或可以用其他前綴唯一描述的庫(如 jakarta-commons-collections 或 apache-ant),則不需要這樣做。
  • 將所有隨程序分發的 jar 文件(而不是其他文件)放在 /usr/share/java/程序目錄下。這包括隨程序分發的所有依賴 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/程序/程序.jar' "$@"
尋找單個類文件的應該類似這樣:
#!/bin/sh
exec /usr/bin/java '/usr/share/java/程序/程序類名' "$@"
  • 使用 -cp 選項為 Java 解釋器設置 CLASSPATH,除非有明確的理由不這樣做(即:CLASSPATH 用於插件機制)。CLASSPATH 應該包括 /usr/share/java/程序目錄下的所有 jar 文件,以及已被重構到其他目錄中的依賴庫的 jar 文件。可以使用類似以下代碼:
for name in /usr/share/java/程序/*.jar ; do
  CP=$CP:$name
done
CP=$CP:/usr/share/java/dep1/dep1.jar
java -cp $CP 程序.java.MainClass
  • 確保 Shell 腳本可執行!
  • 隨軟件包一起分發的其他文件應存放在 /usr/share 下以該軟件包命名的目錄中。你可能需要在 Shell 腳本中的 項目_HOME 等變量中設置該目錄的位置。本準則假設程序希望所有文件都在同一目錄下(這是 Java 軟件包的標準做法)。如果配置文件更適合放在其他地方(例如,把日誌放在 /var/log 中),則可以這樣做。
請記住,在某些系統上 /usr 可能被掛載為只讀。如果應用程式需要寫入共享目錄中的文件,它們可能需要被重新定位到/etc/var 或用戶的主目錄。
  • 與其他 Arch Linux 軟件包的標準一樣,如果遵守上述標準需要做大量的工作,則應以其偏好的方式安裝軟件包,並將生成的目錄放在 /opt 中。這對於捆綁 JRE、包含自定義版本的依賴或做其他奇怪和痛苦的事情的程序很有用。

多個API實現[編輯 | 編輯原始碼]

如果軟件包分發了常用的 API 實現(比如 jdbc 驅動),則應該把庫放在 /usr/share/java/API_名稱 下。這樣,允許用戶選擇實現的應用程式會知道在哪裏尋找它們。這個位置只用於庫包本身。如果這樣的實現是應用程式分發的一部分,不要將這個 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 編寫的軟件只需要 java-runtime

需要將 Java 原始碼編譯到字節碼的軟件包需要 java-environment(如 JDK)。

更多信息參見 Java