目前我们正在为大型项目(大约2000个源文件)重新编写所有构建系统的脚本,并且已经谈到对文件进行二进制比较以确保一切正确,这导致以下问题: javac
的输出是否保证在编辑中相同,还是可以更改?
Another question暗示常量池可能有不同的顺序,但假设我们能够控制进入javac
调用的文件的顺序是否仍存在差异的可能性?我们正在使用Ant和Maven作为构建的一部分,如果它也可能影响事物。
答案 0 :(得分:3)
字节码绝对不保证是相同的;首先,允许编译器执行不影响任何保证行为的优化。 Java语言规范甚至在一些地方提到了编译器可能执行的优化;例如,在字符串连接运算符+
中,它注意到:
实现可以选择在一个步骤中执行转换和连接,以避免创建然后丢弃中间
String
对象。为了提高重复字符串连接的性能,Java编译器可以使用StringBuffer
类或类似技术来减少通过表达式求值创建的中间String
对象的数量。
[link]
答案 1 :(得分:0)
我不是编译器的专家,但我倾向于相信其他答案说二进制比较不是100%可靠。
我考虑另一种选择:您应该能够检查构建系统创建的工件(.jars& .wars等)并确保每个工件都具有预期的内容,甚至是每个文件的大小是在一个相当严格的容忍范围内。
如果您的构建脚本正在生成源代码并对其进行编译,那么您应该能够对生成的源进行比较,我希望从构建到构建将 100%稳定。 (或至少可以预测)。
希望这有帮助!
答案 2 :(得分:0)
确保等价的唯一方法是获取几个类文件解析器中的一个,解析文件,然后执行繁重的工作,找出由于常量池顺序更改等导致的差异。主要问题是重新排序常量pool将更改引用常量的数值,其中一些是表元素,其中一些是字节码。可行,但绝对不重要,并且可能不实用,除非您已经出于某些其他原因(例如字节码修改)已经拥有大部分框架。