【发布时间】:2019-03-13 20:36:35
【问题描述】:
我的雇主有业务需要使 Java 构建逐字节可重复。我知道使 JAR 文件可重现的困难(由于归档顺序和时间戳),但此时我正在谈论类文件。
我在 Mac 和 Linux 上都使用 Java 8u65 构建了相同的代码。类文件是二进制不同的。两个类都反编译回相同的源;要查看差异需要使用 javap 反汇编程序。
源代码好像是:
final TrustStrategy acceptingTrustStrategy =
(X509Certificate[] chain, String authType) -> true;
在一次构建中,结果是:
private static boolean lambda$restTemplate$38(java.security.cert.X509Certificate[], java.lang.String) throws java.security.cert.CertificateException;
Code:
0: iconst_1
1: ireturn
另一方面,它是:
private static boolean lambda$restTemplate$15(java.security.cert.X509Certificate[], java.lang.String) throws java.security.cert.CertificateException;
Code:
0: iconst_1
1: ireturn
匿名 lambda 的名称中包含不同的数字(lambda$restTemplate$15 与 lambda$restTemplate$38)。
看来,当我在同一主机上重建时,我得到了相同的字节。当主机不同时,数字会改变;两台 Linux 主机产生不同的字节。
是什么决定了这些数字?有没有办法强制每个编译在这个地方使用相同的数字,从而产生相同的类文件?还是 Java 8 类文件编译不确定?
【问题讨论】:
-
同一位置的不同计数器值表示 lambda 以不同的顺序编译。序列保存在这里:hg.openjdk.java.net/jdk8/jdk8/langtools/file/1ff9d5118aae/src/…
-
上面的“不同的计数器值”评论本身几乎就是一个答案。计数器值是否可以以任何方式控制?它是按源文件还是按 javac 调用重置?
-
@RobertMandeville:在不确切知道如何构建代码的情况下很难诊断,但有一些建议需要检查,大多数文件系统以任意顺序返回目录列表,这通常取决于文件/目录条目在磁盘上进行物理组织。当您在文件夹中列出文件时,Posix 系统不会定义文件的排序方式,因此您必须排序/请求特定的排序(例如字母数字)。
标签: java lambda javac binary-reproducibility