【发布时间】:2019-03-08 13:45:29
【问题描述】:
我有以下 Java 类
public class HelloWorld {
public static void main(String []args) {
}
}
当我编译这个文件并在生成的类文件上运行 sha256 时,我得到了
9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff HelloWorld.class
接下来我修改了类并添加了一个这样的空行:
public class HelloWorld {
public static void main(String []args) {
}
}
我再次在输出上运行了一个 sha256,期望得到相同的结果,但我得到了
11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f HelloWorld.class
我在this TutorialsPoint article 上看到:
仅包含空格的行,可能带有注释,称为空行,Java 完全忽略它。
所以我的问题是,既然 Java 忽略了空行,为什么两个程序的编译字节码不同?
即HelloWorld.class中的0x03字节被0x04字节替换。
【问题讨论】:
-
请注意,编译器在生成类文件时没有义务是确定性的,即使它们通常是确定性的。见this question。默认情况下,Jar 文件是 not 可重现的,即即使编译 相同的 代码也会产生两个不同的 JAR。那是因为文件的顺序和时间戳不匹配。使用特定配置可以进行可重现的构建。
-
TutorialsPoint 声称 "Java 完全忽略" 空白行。 Section 3.4 of the Java Language Specification 另有说明。相信哪一个?...
-
@skomisa 规范。
-
@GiacomoAlzetta 对于单个字节码文件,甚至没有指定的字节码形式。例如,成员的顺序是未指定的,因此如果编译器使用新的不可变
Sets 并在内部进行随机化,则它可能会在每次运行时产生不同的顺序。它还可以添加包含编译时间的自定义属性。等等…… -
@DioPhung 另一个教训:tutorialspoint 不是好的教程的可靠来源
标签: java compilation javac bytecode