当前位置: 首页 > 面试题库 >

Java类文件的创建是否确定性的?

乐正迪
2023-03-14
问题内容

当使用 相同的JDK (即相同的javac可执行文件)时,生成的类文件是否始终相同?取决于 操作系统硬件
,会有所区别吗?除JDK版本外,是否还有其他因素导致差异?是否有任何编译器选项来避免差异?是仅在理论上可能有所不同,还是Oracle
javac实际上针对相同的输入和编译器选项生成了不同的类文件?

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

更新2 “相同的JDK”也指相同的javac可执行文件。

Update 3 在Oracle编译器中的理论差异和实践差异之间的区别。

[编辑,添加释义的问题]
“在不同平台上运行相同的javac可执行文件时,在什么情况下会产生不同的字节码?”


问题答案:

让我们这样说:

我可以很容易地生成一个完全符合标准的Java编译器,在.class给定相同.java文件的情况下,它永远不会两次生成相同的文件。

我可以通过调整各种字节码构造或通过简单地在我的方法中添加多余的属性(允许)来做到这一点。

鉴于该 规范 并不 要求 编译器生成的字节对字节相同的类文件,我会 避免依赖 这样的结果。

但是 ,我检查过几次,使用相同的编译器和相同的开关(和相同的库!)编译相同的源文件 确实会 得到相同的.class文件。

更新: 我最近偶然发现了关于Java 7 中switchon
的实现的一篇有趣的博客文章String
。在此博客文章中,有一些相关的部分,我将在这里引用(重点是我的):

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

这很清楚地说明了这个问题:只要编译器符合规范,就 不需要 以确定性的方式进行操作。但是,编译器开发人员意识到 尝试 通常
是一个好主意(前提是它可能不太昂贵)。 __



 类似资料:
  • 当使用相同的JDK(即相同的可执行文件)时,生成的类文件是否总是相同的?是否会因操作系统或硬件的不同而有所不同?除了JDK版本之外,还有其他因素导致差异吗?有没有避免差异的编译器选项?这仅仅是理论上的差异,还是Oracle的实际上为相同的输入和编译器选项生成了不同的类文件? 更新1我感兴趣的是生成,即编译器输出,而不是类文件是否可以在各种平台上运行。 更新2同样的JDK,我也指同样的javac可执

  • 问题内容: 在StackOverflow上还有一个类似的问题要问(如何在Java中获取文件的创建日期),但实际上并没有答案,因为OP具有可以通过其他机制解决的不同需求。我试图在目录中创建文件列表,该文件列表可以按年龄排序,因此需要文件创建日期。 在大量浏览网络后,我还没有找到执行此操作的任何好方法。是否有获取文件创建日期的机制? 当前在Windows系统上的BTW可能也需要在Linux系统上工作。

  • 问题内容: 我在Java中使用PdfBox从PDF文件提取文本。提供的某些输入文件无效,这些文件上的PDFTextStripper暂停。有没有一种干净的方法来检查提供的文件是否确实是有效的PDF? 问题答案: 您可以找出文件(或字节数组)的mime类型,因此不必盲目地依赖扩展名。我是用光圈的MimeExtractor(http://aperture.sourceforge.net/)来完成的,或者

  • 问题内容: 自从我使用Java以来​​已经有5年了,那时,每当您想分配需要清理的对象(例如套接字,DB句柄)时,都必须记住添加一个块并在其中调用cleanup方法。那里。 相比之下,在C++(或确定对象生存期的其他语言,例如Perl)中,类实现程序将定义一个析构函数,该函数在该类的对象超出范围时执行清除。这种方法的优点是对象的用户不会忘记清理它- 即使抛出异常,析构函数也会被自动调用。这种方法用R

  • 问题内容: 我 从http 函数进行了如下简单 下载 (为简化起见,省略了错误处理): 但是,由于我异步调用了数十次,因此很少有人报告错误,因为抱怨无法在找到文件。 我使用了相同的URL列表进行测试,但失败了大约30%。一次下载一个相同的URL列表。 测试了一下,我发现下面的代码 并非总是打印,但有时第一个答案打印。 我怀疑太多的异步调用不能保证文件的创建。这是真的?有什么方法可以保证文件创建?