有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java创建。jar文件具有决定性(每次都相同)

我使用jar命令来构建jar文件。在尝试使用md5签名缓存jar文件时,我发现从完全相同的源构建的jar具有不同的md5签名。
仔细检查后,我发现每次创建罐子时,内容都完全相同(diff-qr是空的)。事实证明,创建的时间戳是在jar文件中编码的,它抛出了md5签名。其他人也发现了同样的问题

甚至还有一个blog post关于如何使用maven每次都以相同的方式创建jar文件。然而,我想要一个简单的解决方案,使用命令行,使用诸如jar和zip等现成的命令(可能必须在没有安装权限的服务器上执行此操作),这可能会导致与我当前使用jar命令得到的相同的“功能性”jar

EDIT:就我而言,它还足以快速找到md5,使其在各个构建中都相同,即使JAR不相同。到目前为止,我找到的唯一方法是提取jar中的文件,并将所有组件文件转换为md5。但我担心,对于更大的罐子来说,这太慢了,而且会破坏缓存它们以避免首先构建它们的目的。有更好更快的解决方案吗


共 (2) 个答案

  1. # 1 楼答案

    主要问题是jar命令始终使用当前时间创建META-INF\MANIFEST.MF。 文件时间保存在zip条目标题中。这就是为什么即使jar中的所有文件内容保持不变,MD5值也不同的原因: 不同的zip条目头生成不同的zip文件

    对于jar命令,唯一的解决方案是选项-M:不为条目创建清单文件

  2. # 2 楼答案

    Jar命令始终创建META-INF\MANIFEST。MF与当前时间一致。Zip存储具有时间戳和文件属性的文件,因此两个工件的sha256或MD5将不同

    我们需要确保创建、上次修改、访问的时间戳和文件属性始终与创建jar或zip所需的所有文件相同

    我已经创建了下面的脚本,它可以获取一个jar或zip文件,并通过使时间戳保持不变和设置正确的压缩级别和偏移量使其具有确定性

    #!/bin/bash
    
    usage() {
        echo "Usage : ./createDeterministicArtifact.sh <zip/jar file name>"
        exit 1
    }
    
    info() {
        echo "$1"
    }
    
    strip_artifact() {
        if [ -z ${file} ]; then
            usage
        fi
        if [ -f ${file} -a -s ${file} ]; then
            mkdir -p ${file}.tmp
            unzip -oq -d ${file}.tmp ${file}
            find ${file}.tmp -follow -exec touch -a -m -t 201912010000.00 {} \+
            if [ "$UNAME" == "Linux" ] ; then
                find ${file}.tmp -follow -exec chattr -a {} \+
            elif [[ "$UNAME" == CYGWIN* || "$UNAME" == MINGW* ]] ; then
                find ${file}.tmp -follow -exec attrib -A {} \+
            fi
            cd ${file}.tmp
            zip -rq -D -X -9 -A  compression-method deflate  ../${file}.new . 
            cd -
            rm -rf ${file}.tmp
            info "Recreated deterministic artifact: ${file}.new"
        else 
            info "Input file is empty. Please validate the file and try again"
        fi
    }
    
    file=$1