Java 类文件的创建是确定性的吗? [英] Is the creation of Java class files deterministic?

查看:24
本文介绍了Java 类文件的创建是确定性的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用相同的 JDK(即相同的 javac 可执行文件)时,生成的类文件是否总是相同的?操作系统硬件是否会有所不同?除了JDK版本,是否还有其他因素导致差异?是否有任何编译器选项可以避免差异?仅在理论上可能存在差异还是 Oracle 的 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?

更新1我对生成感兴趣,即编译器输出,而不是一个类文件是否可以在各种平台上运行.

Update 1 I'm interested in the generation, i.e. compiler output, not whether a class file can be run on various platforms.

更新 2相同的 JDK",我也指相同的 javac 可执行文件.

Update 2 By 'Same JDK', I also mean the same javac executable.

更新 3 Oracle 编译器的理论差异和实际差异之间的区别.

Update 3 Distinction between theoretical difference and practical difference in Oracle's compilers.


在什么情况下,相同的 javac 可执行文件在不同平台上运行时会产生不同的字节码?"


"What are the circumstances where the same javac executable,when run on a different platform, will produce different bytecode?"

推荐答案

这么说吧:

在给定相同的 .java 文件的情况下,我可以轻松生成完全符合标准的 Java 编译器,该编译器从不生成相同的 .class 文件两次.

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.

然而,我检查了几次,使用相同的编译器和相同的开关(和相同的库!)编译相同的源文件,结果确实在相同的 .class 文件中.

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.

更新:我最近偶然发现了这篇关于switch 在 Java 7 中的 String .在这篇博文中,有一些相关的部分,我将在这里引用(强调我的):

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):

为了使编译器的输出可预测和可重复,这些数据结构中使用的映射和集合是LinkedHashMaps和LinkedHashSets,而不仅仅是HashMapsHashSets.就给定编译期间生成的代码的功能正确性而言,使用HashMapHashSet就可以了;迭代顺序无关紧要.但是,我们发现 javac 的输出不会因系统类的实现细节而变化 是有益的.

In order to make the compiler's output predictable and repeatable, the maps and sets used in these data structures are LinkedHashMaps and LinkedHashSets rather than just HashMaps and HashSets. In terms of functional correctness of code generated during a given compile, using HashMap and HashSet would be fine; the iteration order does not matter. However, we find it beneficial to have javac'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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆