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

如何使用Javac在不同平台上创建二进制相同的类文件?

郎永福
2023-03-14
问题内容

我用Java编写了AWS Lambda函数。我用来上传Lambda
的工具(Terraform)想要使用jar文件的SHA-256哈希值来跟踪是否需要上传新版本的Lambda。

问题在于,不同OS平台(Windows和Linux)上的不同JDK创建的字节码略有不同(即使使用相同的JDK“更新”版本)。这意味着,如果我在Windows上上传了一个lambda,然后在Linux上重新运行了该过程-
它会检测到jar的其他哈希码,并不必要地重新上传lambda jar。

问题 :如何强制javac在不同的OS平台上创建相同的字节码?


问题答案:

您无法执行。关于生成的类文件,有几个未指定的详细信息,例如某些源代码表达式的字节码必须如何看起来准确,或者成员或属性的顺序。

由于不需要每次运行都生成完全相同的文件,因此编译器实现甚至不会尝试。可以公平地假设,当您使用完全相同的输入(不仅是相同的源代码,而且是相同的选项)执行相同的软件时,它会产生相同的输出,但这不仅需要相同的编译器版本,而且同样是JRE。

不幸的是,即使使用相同的实现和输入,也 可能 会有不同的行为。例如,java.util.HashMap在某些Java
7实现中,尝试进行随机化,如果javac将某些工件存储在中,也就不足为奇了HashMap。这不适用于Java 8,但可能适用于Java
9中引入的不可变映射。编译器是否将使用该功能是不可预测的。

因此,如果您发现一个可重复生成完全相同的字节码的特定jdk版本,则现在可以使用它,但必须注意下一个版本可能没有该属性。

到目前为止,尚未解决,即使具有相同的字节码也无法保证具有相同的jar文件,因为未指定jar文件中文件的顺序。它可能取决于系统特定的文件迭代顺序。此外,由于jar文件是存储时间戳的zip文件,因此,除非您采取其他措施(例如,对所有条目强制使用特定的时间戳),否则新编译的类文件肯定会产生不同的文件。



 类似资料:
  • 假设我有一个表'some-table',我想在多个模式中创建它。名为“create-some-table.yaml”的文件 最后一个是changelog-master,它非常简单 有什么办法我可以做类似这样的事情吗,谢谢:)

  • 我试图为不同的包设置单独的日志文件。我使用一个包装类的记录器。我的应用程序中的每个类都调用相同的包装器类。我的包装类: 这就是所谓的: 有没有办法配置log4j,以便将不同包的日志记录输出到不同的文件? 谢谢! 编辑: 这是我的文件:

  • 我使用一个Android库,它要求我创建两个类,每个类继承自不同的类 (具有公共基类) 现在我有这个代码: 我必须复制这个类来创建一个扩展,即使我的两个类共享完全相同的代码。 我简化了示例的代码,但重复可能很重要 我决定将代码放在这两个类之外的静态方法中,并在类重写的方法中调用它们,但我认为必须有一种更干净的方法来做到这一点。 你能帮我解决这个问题吗? 和都继承自。

  • 假设一个对象有10个实例,其中有一些字段。其中一个字段指定ID。另外两个字段包含有关位置(纬度和经度)的数据。一个字段包含日期时间信息。 在这10个例子中,ID保持不变,但与日期、时间和位置相关的字段发生了变化。 上述数据是虚拟数据。但你可以观察到id保持不变,只是位置和时间发生了变化。 使用java, sping-data-elasticsearch我能够把信息在弹性搜索。 我面临的问题是,在弹

  • 问题内容: 谁能解释相同的Java源代码最终如何编译成 二进制 不同的类文件? 问题来自以下情况: 我们有一个相当大的应用程序(800多个类),该应用程序已经分支,重组并重新集成到主干中。在重新集成之前,我们将主干合并到分支中,这是标准过程。 最终结果是一组包含分支源的目录和一组包含中继源的目录。使用“超越比较”,我们能够确定两组来源相同。但是,在编译时(使用IntelliJ v11中托管的mav

  • 问题内容: 一些旧代码依赖于平台的默认字符集进行翻译。对于“西方世界”中的Windows和Linux安装,我知道这意味着什么。但是考虑到俄罗斯或亚洲平台,我完全不确定其平台的默认字符集是什么(只是UTF-16?)。 因此,我想知道执行以下代码行会得到什么: PS: 我不想在这里讨论字符集的问题及其与Unicode的区别。我只想收集什么操作系统会导致什么特定字符集。请仅发布具体值! 问题答案: 这是