Jar

說明

將一組檔案打包成 Jar。

basedir 屬性是打包 Jar 的參考目錄。

請注意,檔案權限不會儲存在產生的 jar 檔中。

可以調整要打包成 Jar 的檔案組。這可以使用 includesincludesfileexcludesexcludesfiledefaultexcludes 屬性來完成。使用 includesincludesfile 屬性,您可以使用模式指定要包含的檔案。excludeexcludesfile 屬性用於指定要排除的檔案。這也是使用模式來完成的。最後,您可以使用 defaultexcludes 屬性指定是否要使用預設的排除規則。有關如何包含/排除檔案以及如何撰寫模式的資訊,請參閱 基於目錄的任務 部分。

此任務會形成一個隱含的 FileSet,並支援 <fileset> 的大多數屬性(dir 變成 basedir),以及巢狀的 <include><exclude><patternset> 元素。

您也可以使用巢狀檔案組來獲得更大的彈性,並指定多個檔案組,將不同的檔案樹合併成一個 JAR。zip 任務中的延伸 filesetgroupfileset 子元素也可以在 jar 任務中使用。有關更多詳細資訊和範例,請參閱 Zip 任務。

update 參數控制 JAR 檔案已存在時會發生什麼事。設定為 yes 時,JAR 檔案會使用指定的檔案更新。設定為 no(預設值)時,JAR 檔案會被覆寫。有關此功能的範例使用方式,請參閱 Zip 任務文件。請注意,ZIP 檔案會以 2 秒為單位儲存檔案修改時間。如果檔案比封存中的項目新不到 2 秒,Ant 就不會將其視為較新。

如果省略清單,Apache Ant 會提供一個簡單的清單。

當除了清單檔案或巢狀服務外,沒有任何檔案符合時,whenmanifestonly 參數會控制發生什麼情況。如果為 skip,則不會建立 JAR,並會發出警告。如果為 fail,則不會建立 JAR,並會以錯誤終止建置。如果為 create(預設值),則會建立一個空的 JAR 檔案(僅包含清單和服務)。

Jar 任務有一個捷徑,可以用於指定 JAR 檔案的清單檔案。也可以使用 Zip 任務中 zipfilesetfullpath 屬性來完成相同的事情。唯一的差別是,如果未指定 manifest 屬性,Jar 任務會自動為您包含一個空的屬性。)

清單會根據 Jar 檔案規格Jar 任務處理。特別注意,這可能會導致大於 72 位元的清單行換行並延續到下一行。

Jar 任務會檢查您是否根據 版本控制規格 指定套件資訊。

請注意,ZIP 格式允許多個具有相同完全限定名稱的檔案存在於單一檔案庫中。已記錄這會對毫無戒心的使用者造成各種問題。如果您希望避免這種行為,您必須將 duplicate 屬性設定為預設值 add 以外的值。

若要對 JAR 檔案進行加密簽署,請對您從此任務建立的 JAR 使用 SignJar 任務

若要建立 JEP 238 多重發行 JAR 的簡易版本,您不需要任何特殊工具。只要設定必要的 manifest 項目,並將檔案放置在必要的位置,正如您在 JEP 238 範例 中所見。如果您想要調整這種 JAR,例如透過從版本分支刪除「相同」類別來縮小大小,您必須執行更多操作...

參數

屬性 說明 必要
destfile 要建立的 JAR 檔案。
basedir 要將檔案封裝成 JAR 的目錄。
compress 不僅儲存資料,還會壓縮資料。除非您將 keepcompression 屬性設定為 false,否則這會套用至整個檔案庫,而不僅是您在更新時新增的檔案。 否;預設為 true
keepcompression 對於來自現有檔案庫的項目(例如巢狀 zipfileset 或在更新檔案庫時),保留壓縮,如同原本的,而不是使用 compress 屬性。自 Ant 1.6 起 否;預設為 false
encoding 用於檔案庫內檔案名稱的字元編碼。不建議變更此值,否則建立的檔案庫很可能無法用 Java 讀取。
另請參閱 zip 任務頁面中的討論
否;預設為 UTF8
filesonly 僅儲存檔案條目 否;預設為 false
includes 必須包含的檔案模式的逗號或空格分隔清單 否;預設為全部 (**)
includesfile 檔案名稱。此檔案的每一行都被視為包含模式
excludes 必須排除的檔案模式的逗號或空格分隔清單 否;預設為預設排除或 defaultexcludesno 時沒有
excludesfile 檔案名稱。此檔案的每一行都被視為排除模式
defaultexcludes 表示是否應使用預設排除 (yes|no) 否;預設為 yes
manifest 要使用的清單檔案。這可以是清單的位置,也可以是透過檔案集新增的 jar 的名稱。如果它是新增 jar 的名稱,則任務會預期清單在 jar 中位於 META-INF/MANIFEST.MF
filesetmanifest zipfilesetzipgroupfileset 檔案中找到清單時的行為。有效值為 skipmergemergewithoutmainmerge 會合併所有清單,並將其合併到任何其他指定的清單中。mergewithoutmain 會合併清單中除了 Main 區段以外的所有內容。 否;預設為 skip
update 表示如果目標檔案已存在,是否要更新或覆寫它 否;預設為 false
whenmanifestonly 當沒有檔案符合時,行為。有效值為 failskipcreate 否;預設為 create
duplicate 找到重複檔案時的行為。有效值為 addpreservefail 否;預設為 add
index 是否建立 索引清單 以加快類別載入。除非您使用嵌套的 indexjars 元素指定其他 jar,否則只有此 jar 的內容會包含在索引中。 否;預設為 false
indexMetaInf 是否將 META-INF 及其子項包含在索引中。如果 indexfalse,則不會產生任何影響。
Sun 的 jar 實作過去會略過 META-INF 目錄,而 Ant 也遵循此範例。此行為已在 Java 5 中變更。為了避免在 Java 1.4 或更早版本的 Ant 上使用 Ant 產生的 jar 時出現問題,Ant 只有在明確要求時才會包含 META-INF自 Ant 1.8.0 起
否;預設為 false
manifestencoding 當指定清單檔案時,用於讀取 JAR 清單的編碼。此工作在寫入清單時將永遠使用 UTF-8。 否;預設為 JVM 字元編碼
roundup 檔案修改時間是否會進位到下一偶數秒數。
Zip 檔案以 2 秒為單位儲存檔案修改時間,因此時間會進位或捨去。如果您捨去,當您重新執行工作時,檔案會永遠顯示為過期,因此預設為進位。進位可能會導致其他類型的問題,例如 Web 檔案中的 JSP 看起來比預編譯頁面稍微新一點,導致預編譯無用。自 Ant 1.6.2 起
否;預設為 true
level 執行檔案壓縮的非預設層級。有效值範圍從 0(無壓縮/最快)到 9(最大壓縮/最慢)。自 Ant 1.7 起
strict 設定如何處理封裝版本規格中斷
  • fail = 擲出 BuildException
  • warn = 以警告層級記錄訊息
  • ignore = 以詳細層級記錄訊息(預設)
自 Ant 1.7.1 起
否;預設為 ignore
preserve0permissions 更新檔案或從不同檔案新增項目時,Ant 會假設 Unix 權限值 0(任何人都不允許對檔案/目錄執行任何操作)表示權限根本未儲存,而不是實際權限,並會套用其自己的預設值。
如果您真的想保留原始權限欄位,請將此屬性設定為 true自 Ant 1.8.0 起
否;預設為 false
useLanguageEncodingFlag 如果編碼為 UTF-8,是否設定語言編碼標記。如果編碼不是 UTF-8,此設定不會產生任何效果。自 Ant 1.8.0 起
另請參閱 zip 任務頁面中的討論
否;預設為 true
createUnicodeExtraFields 是否建立 Unicode 額外欄位,以在項目的元資料中第二次儲存檔案名稱。
可能的值為 neveralwaysnot-encodeable,後者僅在檔案名稱無法編碼時才會新增 Unicode 額外欄位。
另請參閱 zip 任務頁面中的討論
否;預設為 never
fallbacktoUTF8 如果無法使用指定的編碼編碼檔案名稱,是否改用 UTF-8 和語言編碼旗標。自 Ant 1.8.0 起
另請參閱 zip 任務頁面中的討論
否;預設為 false
mergeClassPathAttributes 是否合併在不同清單中找到的 Class-Path 屬性(如果合併清單)。如果為 false,則只會保留最後合併清單的屬性。自 Ant 1.8.0 起
除非您也將 flattenAttributes 設定為 true,否則這可能會導致清單包含多個 Class-Path 屬性,這會違反清單規格。
否;預設為 false
flattenAttributes 是否將在區段中出現多次的屬性(這只會發生在 Class-Path 屬性)合併成單一屬性。自 Ant 1.8.0 起 否;預設為 false
zip64Mode 何時對項目使用 Zip64 延伸模組。可能的數值為 neveralwaysas-needed自 Ant 1.9.1 起
另請參閱 zip 任務頁面中的討論
否;預設為 never
modificationtime 將所有儲存的檔案修改時間設定為指定時間。這可以是解釋為自 1970-01-01T00:00:00Z 以來的毫秒數的數字,或可以解析為 ISO 8601 時間戳記(包含時區選項)的字串。自 Ant 1.10.2 起

以巢狀元素指定的參數

metainf

巢狀 metainf 元素指定 FileSet。此檔案集中包含的所有檔案都將出現在 jar 檔案的 META-INF 目錄中。如果此檔案集包含名為 MANIFEST.MF 的檔案,則該檔案將會被忽略,而且您會收到警告。

manifest

巢狀 manifest 元素允許在建置檔案中內嵌 Jar 檔案的清單,而不是在外部檔案中。此元素與 manifest 任務相同,但必須省略 filemode 屬性。

如果同時指定內嵌清單和外部檔案,則會合併清單。

使用內嵌清單時,Jar 任務將檢查清單內容是否已變更(例如,指定之清單與 jar 中存在的清單(如果存在)有任何不同。如果清單值已變更,將視需要更新或重新建置 jar。

indexjars

自 Ant 1.6.2 起

巢狀 indexjars 元素指定 類似的路徑結構。除非您將任務的 index 屬性設定為 true,否則會完全忽略其內容。

此任務建立的索引將包含此路徑中所含檔案的索引,用於檔案的名稱取決於您的清單

此任務不會為空檔案或僅包含 META-INF 目錄內檔案的檔案建立任何索引項目,除非 indexmetainf 屬性已設定為 true

indexjarsmapper

自 Ant 1.10.9 起

如果 預設檔案名稱轉換 不夠用,可以使用巢狀 indexjarsmapper 元素為 indexjars 指定的檔案執行自訂檔案名稱轉換。

service

自 Ant 1.7.0 起

巢狀 service 元素指定服務。服務在 服務提供者概觀 中說明。方法是讓提供者 JAR 包含由所提供的服務命名的檔案,例如,META-INF/services/javax.script.ScriptEngineFactory,其中可以包含實作類別名稱,每行一個(通常每個 JAR 僅一個)。

服務名稱由 type 屬性設定。實作服務的類別名稱是 provider 屬性,或者如果要指定多個實作服務的類別,則由 provider 巢狀元素指定。

屬性 說明 必要
type 服務的名稱。
提供者 實作服務的類別類別名稱。 是的,除非有巢狀的 <provider> 元素。

提供者類別名稱由 provider 屬性或具有單一 classname 屬性的巢狀 <provider> 元素指定。如果 JAR 檔案有多個服務實作,可以使用多個巢狀 <provider> 元素。

範例

簡單

${build}/classes 目錄中的所有檔案封裝成 JAR 檔案,稱為 app.jar,並儲存在 ${dist}/lib 目錄中。

<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes"/>

使用篩選器

${build}/classes 目錄中的所有檔案封裝成 JAR 檔案,稱為 app.jar,並儲存在 ${dist}/lib 目錄中。名稱為 Test.class 的檔案會被排除。

<jar destfile="${dist}/lib/app.jar"
     basedir="${build}/classes"
     excludes="**/Test.class"/>

${build}/classes 目錄中的所有檔案封裝成 JAR 檔案,稱為 app.jar,並儲存在 ${dist}/lib 目錄中。僅使用 mypackage/test 目錄下的檔案,並排除名稱為 Test.class 的檔案。

<jar destfile="${dist}/lib/app.jar"
     basedir="${build}/classes"
     includes="mypackage/test/**"
     excludes="**/Test.class"/>

多個檔案集

${build}/classes 目錄和 ${src}/resources 目錄中的所有檔案封裝成 JAR 檔案,稱為 app.jar,並儲存在 ${dist}/lib 目錄中。名稱為 Test.class 的檔案會被排除。如果有 ${build}/classes/mypackage/MyClass.class${src}/resources/mypackage/image.gif 等檔案,它們會出現在 JAR 檔案中的同一個目錄中(因此 Java 會將它們視為同一個套件)。

<jar destfile="${dist}/lib/app.jar">
    <fileset dir="${build}/classes"
             excludes="**/Test.class"/>
    <fileset dir="${src}/resources"/>
</jar>

合併檔案

建立一個主類別為 com.acme.checksites.Main 的可執行 JAR 檔案,並嵌入 JAR lib/main/some.jar 中的所有類別。

<jar destfile="build/main/checksites.jar">
    <fileset dir="build/main/classes"/>
    <zipfileset includes="**/*.class" src="lib/main/some.jar"/>
    <manifest>
      <attribute name="Main-Class"
                 value="com.acme.checksites.Main"/>
    </manifest>
</jar>

建立一個主類別為 com.acme.checksites.Main 的可執行 JAR 檔案,並嵌入 lib/main 中所有 JAR 的所有類別。

<jar destfile="build/main/checksites.jar">
    <fileset dir="build/main/classes"/>
    <restrict>
       <name name="**/*.class"/>
       <archives>
           <zips>
               <fileset dir="lib/main" includes="**/*.jar"/>
           </zips>
       </archives>
    </restrict>
    <manifest>
        <attribute name="Main-Class"
              value="com.acme.checksites.Main"/>
    </manifest>
</jar>

內嵌清單

<jar destfile="test.jar" basedir=".">
    <include name="build"/>
    <manifest>
        <!-- If this is an Applet or Web Start application, include
             the proper attributes from https://docs.oracle.com/javase/8/docs/technotes/guides/jweb/index.html -->
        <attribute name="Permissions" value="sandbox"/>
        <attribute name="Codebase" value="example.com"/>
        <!-- Who is building this jar? -->
        <attribute name="Built-By" value="${user.name}"/>
        <!-- Information about the program itself -->
        <attribute name="Implementation-Vendor" value="ACME inc."/>
        <attribute name="Implementation-Title" value="GreatProduct"/>
        <attribute name="Implementation-Version" value="1.0.0beta2"/>
        <!-- details -->
        <section name="common/MyClass.class">
            <attribute name="Sealed" value="false"/>
        </section>
    </manifest>
</jar>

以下是內嵌清單規格的範例,其中包含建置程式版本(Implementation-Version)。請注意,Built-By 屬性會採用 Ant 屬性 user.name 的值。上述清單產生的清單會如下所示

Manifest-Version: 1.0
Permissions: sandbox
Codebase: example.com
Built-By: conor
Implementation-Vendor: ACME inc.
Implementation-Title: GreatProduct
Implementation-Version: 1.0.0beta2
Created-By: Apache Ant 1.9.2

Name: common/MyClass.class
Sealed: false

服務提供者

以下說明如何建立一個 JAR 檔案,指定一個具有指令碼介面實作的服務

<jar destfile="pinky.jar">
    <fileset dir="build/classes"/>
    <service type="javax.script.ScriptEngineFactory"
             provider="org.acme.PinkyLanguage"/>
</jar>

以下說明如何建立一個 JAR 檔案,指定一個具有兩個指令碼介面實作的服務

<jar destfile="pinkyandbrain.jar">
    <fileset dir="classes"/>
    <service type="javax.script.ScriptEngineFactory">
        <provider classname="org.acme.PinkyLanguage"/>
        <provider classname="org.acme.BrainLanguage"/>
    </service>
</jar>

JEP 238 範例:多版本 JAR 檔案

在此,我們要根據規格 JEP 238 建立一個多版本 JAR 檔案。它定義在 JAR 之上,可以在 JAR 中放置額外的或覆寫類別,這些類別會根據您執行的 Java 版本而提供。
基本上,它表示您必須設定清單項目 Multi-Release: true,並將所有額外的或覆寫類別放置在 META-INF/versions/number/package-structure 中,例如 META-INF/versions/9/org/apache/ant/MyClass.class

在此範例中,我們預期正常的類別會編譯成 ${java.classes},而 Java 9 類別會編譯成 ${java9.classes}

<jar destfile="mrjar.jar">
    <manifest>
        <!-- special mf-entry according to the spec -->
        <attribute name="Multi-Release" value="true"/>
    </manifest>
    <!-- directory structure according to the spec ... -->
    <!-- ... default classes loadable by old (<Java 9) versions -->
    <fileset dir="${java.classes}"/>
    <!-- ... per release classes, require Java 9+ for loadable via standard ClassLoader -->
    <zipfileset prefix="META-INF/versions/9/" dir="${java9.classes}"/>
</jar>