是Java类文件的创建是确定性的吗? [英] Is the creation of Java class files deterministic?
问题描述
当使用相同的JDK (即相同的 javac
可执行档)时,生成的类文件是否始终相同?根据操作系统或硬件,可能会有差异吗?除了JDK版本,可能有任何其他因素导致差异吗?有没有任何编译器选项,以避免差异?是不是只有可能在理论上或者Oracle的 javac
实际上为相同的输入和编译器选项产生不同的类文件?
更新1 我对生成感兴趣,即编译器输出,而不是类文件是否可以在各种平台上运行。
更新2 通过相同的JDK,我也意味着相同的 javac
可执行文件。
更新3 在Oracle的编译器中区分理论差异和实际差异。
在不同的平台上运行相同的javac可执行文件时,会产生不同的字节码?
让我们用这种方式:
一个完全符合的Java编译器,从不产生相同的 .class
文件两次,给定相同的 .java
文件。 p>
我可以通过调整各种字节码构造或者简单地添加多余的属性到我的方法(这是允许的)。
由于 不需要编译器产生逐字节相同的类文件,因此我会避免依赖这样的结果。
然而,,几次,我检查,编译同一源文件与相同的编译器与相同的开关(和相同的库!)会产生相同的 .class
文件。
更新:我最近偶然发现了这个有趣的博文,介绍了 switch
on String
。在这篇博文中,有一些相关的部分,我会在这里引用(强调我的):
输出可预测和可重复,在这些数据结构中使用的映射和集合
$LinkedHashMap
s和LinkedHashSet
code> HashMaps 和HashSets
。 在给定编译期间的函数正确性方面使用HashMap
和HashSet
会很好;迭代顺序无关紧要。然而,我们发现javac
的输出不会根据系统类的实现细节而变化。
这非常清楚地说明了这个问题:编译器不需要以确定的方式操作,只要它符合规范。然而,编译器开发人员意识到,一般来说, 是一个好主意 (假设它可能不太贵)。
When using the same JDK (i.e. the same javac
executable), are the generated class files always identical? Can there be a difference depending on the operating system or hardware? Except of the JDK version, could there be any other factors resulting in differences? Are there any compiler options to avoid differences? Is a difference only possibly in theory or does Oracle's javac
actually produce different class files for the same input and compiler options?
Update 1 I'm interested in the generation, i.e. compiler output, not whether a class file can be run on various platforms.
Update 2 By 'Same JDK', I also mean the same javac
executable.
Update 3 Distinction between theoretical difference and practical difference in Oracle's compilers.
[EDIT, adding paraphrased question]
"What are the circumstances where the same javac executable,when run on a different platform, will produce different bytecode?"
Let's put it this way:
I can easily produce an entirely conforming Java compiler that never produces the same .class
file twice, given the same .java
file.
I could do this by tweaking all kinds of bytecode construction or by simply adding superfluous attributes to my method (which is allowed).
Given that the specification does not require the compiler to produce byte-for-byte identical class files, I'd avoid depending such a result.
However, the few times that I've checked, compiling the same source file with the same compiler with the same switches (and the same libraries!) did result in the same .class
files.
Update: I've recently stumbled over this interesting blog post about the implementation of switch
on String
in Java 7. In this blog post, there are some relevant parts, that I'll quote here (emphasis mine):
In order to make the compiler's output predictable and repeatable, the maps and sets used in these data structures are
LinkedHashMap
s andLinkedHashSet
s rather than justHashMaps
andHashSets
. In terms of functional correctness of code generated during a given compile, usingHashMap
andHashSet
would be fine; the iteration order does not matter. However, we find it beneficial to havejavac
's output not vary based on implementation details of system classes .
This pretty clearly illustrates the issue: The compiler is not required to act in a deterministic manner, as long as it matches the spec. The compiler developers, however, realize that it's generally a good idea to try (provided it's not too expensive, probably).
这篇关于是Java类文件的创建是确定性的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!