ant如何编译和jar字节相同的jar文件,即MD5匹配,除非.java(以及.class)发生更改



摘要

如何让ant从相同的.class文件中重复生成字节相同的jar文件?

背景

我们的构建过程如下:

  1. 从另一个应用程序的源存储库获取web服务定义(wsdl(文件
  2. 运行wsdl2java生成.java文件供web服务客户端(即我们的应用程序(使用
  3. 编译java文件
  4. 从编译器输出生成.jar文件
  5. 将"artifact"jar文件检查到源代码管理中

注意:我们完成了最后一步,这样开发人员就可以访问这个jar文件,而不用自己构建它。我们使用一个特殊的"派生"目录来区分源和工件。

问题

我们不能让ant生成字节相同的.jar文件,即使源文件没有改变,也就是说,每个构建都会生成一个略有不同的jar(具有不同的MD5(

我在网上查了一下,发现了这个5年前的问题:

如果我编译一些代码并使用ANT创建一个jar和相关的md5文件md5文件中的校验和每次都不同,即使代码没有更改。任何想法都是为什么这是如何规避的?我怀疑某个地方有一些时间戳信息。

http://www.velocityreviews.com/forums/t150783-creating-new-jar-same-code-different-md5.html

根据回复,我尝试了以下操作:

  1. 在jarring之前,将所有.class文件的时间戳设置为"0">
  2. 指定清单文件并将此清单的时间戳设置为0

【注:第二步似乎无效。见下文】

在每次构建之后,.jar文件仍然具有不同的MD5总和。

CSI:Jar文件

我已经取消捕获并检查了罐子,罐子的内容和时间戳在"不同"的罐子之间匹配,只有一个例外:META-INF/MMANIFEST.MF.的时间戳不同

代码

   <-- touch classes and manifest to set consistent timestamp across builds -->
   <touch millis="0">
    <fileset dir="${mycompany.ws.classes.dir}"/>
   </touch>
   <touch millis="0" file="mymanifest.mf"/>
   <jar destfile="${derived.lib.dir}/mycompanyws.jar"
        manifest="mymanifest.mf"
        basedir="${mycompany.ws.classes.dir}"
        includes="**/com/mycompany/**,**/org/apache/xml/**" 
    />

其他选项

如果.java文件发生了更改,我们可以使用更高级的ant编程只签入.jar文件。

我一直面临着类似的问题,但略有不同。我决定在这里分享它,因为它与问题的主题有关。为了在不同的时间生成两个字节相同的数字签名JAR文件,必须考虑以下几点:

  • 时间戳:**/*.class文件必须具有相同的时间戳(java.util.zip.ZipEntry.setTime(long)(。此外,META-INF/MANIFEST.MF文件和证书文件(*.RSA*.DSA*.SF(将添加到带有"现在"时间戳的JAR文件中。因此,即使您决定不编译类并使用已经编译的类(即具有原始JAR时间戳的类(,您得到的JAR也将是二进制的。
  • MANIFEST.MF条目排序:请注意,MANIFEST.MF文件中的键值对表示为java.util.HashMap,而"does not guarantee that the order will remain constant over time."。因此,当使用JDKv5和JDKv6jarsigner工具对JAR文件进行签名时,可能会遇到另一个二进制差异,因为MANIFEST.MF条目的顺序可能会发生变化(http://stackoverflow.com/questions/1879897/order-of-items-in-a-hashmap-differ-when-the-same-program-is-run-in-jvm5-vs-jvm6)。

所以基本上有两个层次的问题。首先,JAR/ZIP工具用文件系统时间戳对文件进行打包,从而为相同的一组Java类创建二进制的不同JAR文件,这些类是二进制的,但在不同的时间编译。其次,JAR签名器工具修改META-INF/MANIFEST-MF文件,并将更多文件附加到JAR归档中(证书和类文件校验和(。

该解决方案可能是一个自定义的JAR签名器,它将所有JAR文件项的时间戳设置为一个恒定的时间,并对MANIFEST.MF文件项进行排序(例如,按字母表(。据我所知,到目前为止,这是在不同时间点生成两个字节相同的数字签名JAR文件的唯一方法。

由于jar只是一个匿名的zip文件,您可以尝试使用zip任务手动将清单文件添加到META-INF/下。希望这能绕过与jar任务处理清单相关的任何内部魔法。

顺便说一句,因为听起来拥有相等的MD5是至关重要的,所以我建议您在构建过程中添加一个健全性测试,例如编译一些从未更改为jar的特殊"伪"代码,并检查jar MD5是否等于预期值。这将保护构建免受意外更改的影响(例如,升级到ant、JRE、OS、时区更改等之后(

遇到了同样的问题,出现在了这个页面上。Jiri Patera的上述回答非常有助于理解为什么在取消签名并放弃jar文件后,我无法获得预期的两个相同文件的md5sum。

这是我使用的解决方案:

jar-tvf$JARFILE|grep-v META-INF|perl-p-e's/^\s+(\d+(.*\s+([\w]+(/$1$2/g'|md5sum

它不能100%确定罐子是等效的,但它给出了一个相当可靠的指示。

它列出jarfile中的所有文件,减去META_INF文件,解析出文件大小和文件名,然后通过md5sum算法运行filesize加文件名的文本。

相关内容

  • 没有找到相关文章

最新更新