将一组文件打包成 Jar 包。
basedir 属性是打包的参考目录。
请注意,生成的 Jar 包中不会存储文件权限。
可以对要打包的文件进行细化。这可以通过 includes、includesfile、excludes、excludesfile 和 defaultexcludes 属性来实现。使用 includes 或 includesfile 属性,您可以使用模式指定要包含的文件。使用 exclude 或 excludesfile 属性指定要排除的文件。这也使用模式来完成。最后,使用 defaultexcludes 属性,您可以指定是否使用默认排除。有关如何进行文件包含/排除以及如何编写模式,请参阅有关 基于目录的任务 的部分。
此任务形成一个隐式的 FileSet,并支持 <fileset>
的大多数属性(dir 变为 basedir),以及嵌套的 <include>
、<exclude>
和 <patternset>
元素。
您还可以使用嵌套的文件集来获得更大的灵活性,并指定多个文件集将不同的文件树合并到一个 JAR 中。zip
任务中的扩展 fileset
和 groupfileset
子元素在 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
任务中 zipfileset
的 fullpath 属性可以实现相同的效果。唯一的区别是,如果未指定 manifest 属性,Jar
任务将为您包含一个空的清单。)
清单由 Jar
任务根据 Jar 文件规范 进行处理。特别要注意,这可能会导致大于 72 字节的清单行被换行并继续到下一行。
Jar
任务检查您是否根据 版本控制规范 指定了包信息。
请注意,ZIP 格式允许在单个存档中存在多个具有相同完全限定名称的文件。这已被记录为对毫无戒心的用户造成各种问题。如果您希望避免这种行为,则必须将 duplicate 属性设置为除其默认值 add
之外的其他值。
要对 JAR 文件进行加密签名,请使用此任务创建的 JAR 上的 SignJar 任务。
要创建 JEP 238 多版本 jar 的简单版本,您不需要任何特殊工具。只需设置所需的 manifest
条目并将文件放置在所需的位置,如 JEP 238 示例 中所示。如果您想调整这种类型的 jar,例如通过从版本分支中删除“相同”类来减小大小,您需要做更多的事情...
属性 | 描述 | 必需 |
---|---|---|
destfile | 要创建的 JAR 文件。 | 是 |
basedir | 打包文件的目录。 | 否 |
compress | 不仅存储数据,还要压缩它们。除非您将 keepcompression 属性设置为 false,否则这将应用于整个存档,而不仅仅是您在更新时添加的文件。 |
否;默认为 true |
keepcompression | 对于来自现有存档(如嵌套的 zipfileset 或更新存档时)的条目,保持其原始压缩方式,而不是使用 compress 属性。自 Ant 1.6 起 |
否;默认为 false |
encoding | 用于存档中文件名字符编码。不建议更改此值,因为否则创建的存档很可能无法被 Java 读取。 另请参阅 zip 任务页面中的讨论 |
否;默认为 UTF8 |
filesonly | 仅存储文件条目 | 否;默认为 false |
includes | 必须包含的文件模式的逗号或空格分隔列表 | 否;默认为全部(**) |
includesfile | 文件名称。此文件的每一行都被视为一个包含模式 | 否 |
excludes | 必须排除的文件模式的逗号或空格分隔列表 | 否;默认为默认排除,如果 defaultexcludes 为 no,则为无 |
excludesfile | 文件名称。此文件的每一行都被视为一个排除模式 | 否 |
defaultexcludes | 指示是否使用默认排除(yes|no) |
否;默认为 yes |
manifest | 要使用的清单文件。这可以是清单的位置,也可以是通过文件集添加的 jar 的名称。如果它是添加的 jar 的名称,则任务期望清单位于 jar 中的 META-INF/MANIFEST.MF 中 | 否 |
filesetmanifest | 在 zipfileset 或 zipgroupfileset 文件中找到清单时的行为。有效值为 skip、 merge和 mergewithoutmain。 merge将所有清单合并在一起,并将此合并到任何其他指定的清单中。 mergewithoutmain合并所有内容,但清单的主部分除外。 |
否;默认为 skip |
update | 指示如果目标文件已存在,是否更新或覆盖它 | 否;默认为 false |
whenmanifestonly | 当没有文件匹配时的行为。有效值为 fail、 skip和 create。 |
否;默认为 create |
duplicate | 找到重复文件时的行为。有效值为 add、 preserve和 fail。 |
否;默认为 add |
index | 是否创建 索引列表 以加快类加载速度。除非您使用嵌套的 indexjars 元素指定其他 jar,否则只有此 jar 的内容将包含在索引中。 |
否;默认为 false |
indexMetaInf | 是否将 META-INF 及其子目录包含在索引中。如果 index 为 false,则没有任何效果。 Sun 的 jar 实现过去会跳过 META-INF 目录,Ant 遵循了该示例。该行为已在 Java 5 中更改。为了避免在 Java 1.4 或更早版本上使用 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 | 配置如何处理打包版本规范的违规
|
否;默认为 ignore |
preserve0permissions | 在更新存档或从其他存档添加条目时,Ant 将假设 Unix 权限值为 0(没有人被允许对文件/目录执行任何操作)意味着权限根本没有存储,而不是实际权限,并将改为应用其自己的默认值。 如果您确实要保留原始权限字段,请将此属性设置为 true。自 Ant 1.8.0 起 |
否;默认为 false |
useLanguageEncodingFlag | 如果编码为 UTF-8,是否设置语言编码标志。如果编码不是 UTF-8,则此设置没有任何效果。自 Ant 1.8.0 起。 另请参阅 zip 任务页面中的讨论 |
否;默认为 true |
createUnicodeExtraFields | 是否创建 Unicode 额外字段以在条目元数据中第二次存储文件名。 可能的值为 never、 always和 not-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 扩展。可能的值为 never、 always和 as-needed。自 Ant 1.9.1 起。 另请参阅 zip 任务页面中的讨论 |
否;默认为 never |
modificationtime | 将所有存储的文件修改时间设置为给定时间。这可以是解释为自 1970-01-01T00:00:00Z 以来的毫秒数,也可以是可解析为带可选时区的 ISO 8601 时间戳的字符串。自 Ant 1.10.2 起。 | 否 |
嵌套的 metainf
元素指定一个 FileSet。此文件集中包含的所有文件最终将位于 jar 文件的 META-INF 目录中。如果此文件集包含一个名为 MANIFEST.MF 的文件,则该文件将被忽略,您将收到警告。
嵌套的manifest
元素允许在构建文件中内联提供 Jar 文件的清单,而不是在外部文件中。此元素与manifest任务相同,但必须省略file和mode属性。
如果同时指定了内联清单和外部文件,则会合并这些清单。
使用内联清单时,Jar
任务将检查清单内容是否已更改(即,指定的清单是否与 jar 中存在的清单(如果存在)有任何不同。如果清单值已更改,则将根据需要更新或重建 jar。
自 Ant 1.6.2 起
嵌套的indexjars
元素指定一个类似路径的结构。除非将任务的index属性设置为true
,否则其内容将被完全忽略。
此任务创建的索引将包含此路径中包含的存档的索引,用于存档的名称取决于您的清单
Class-Path
属性,则将使用没有任何前导目录路径的文件名,并且路径的所有部分都将被索引。Class-Path
属性,此任务将尝试猜测Class-Path
的哪一部分属于给定的存档。如果无法猜测名称,则将跳过存档,否则将使用Class-Path
属性中列出的名称。此任务不会为为空或仅包含META-INF目录中的文件的存档创建任何索引条目,除非indexmetainf属性已设置为true
。
自 Ant 1.10.9 起
如果默认文件名转换不足,则可以使用嵌套的indexjarsmapper
元素对indexjars
指定的存档执行自定义文件名转换。
自 Ant 1.7.0 起
嵌套的service
元素指定一个服务。服务在服务提供者概述中进行了描述。该方法是让提供者 JAR 包含以提供的服务命名的文件,例如META-INF/services/javax.script.ScriptEngineFactory,其中可以包含实现类名,每行一个(通常每个 JAR 只有一个)。
服务的名称由type属性设置。实现服务的类名是provider属性,或者如果要指定多个实现服务的类,则通过provider
嵌套元素。
属性 | 描述 | 必需 |
---|---|---|
type | 服务的名称。 | 是 |
provider | 实现服务的类的类名。 | 是的,除非存在嵌套的<provider> 元素。 |
提供者类名由provider属性或嵌套的<provider>
元素指定,该元素具有单个classname属性。如果 JAR 文件具有多个服务的实现,则可以使用多个嵌套的<provider>
元素。
将${build}/classes目录中的所有文件打包到${dist}/lib目录中名为app.jar的文件中。
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes"/>
将${build}/classes目录中的所有文件打包到${dist}/lib目录中名为app.jar的文件中。排除名为Test.class的文件。
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes" excludes="**/Test.class"/>
将${build}/classes目录中的所有文件打包到${dist}/lib目录中名为app.jar的文件中。仅使用mypackage/test目录下的文件,并排除名为Test.class的文件。
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes" includes="mypackage/test/**" excludes="**/Test.class"/>
将${build}/classes目录和${src}/resources目录中的所有文件一起打包到${dist}/lib目录中名为app.jar的文件中。排除名为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>
创建一个可执行的 jar 文件,其主类为com.acme.checksites.Main,并将来自 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>
创建一个可执行的 jar 文件,其主类为com.acme.checksites.Main,并将来自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 文件。它在 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>