假设JDK版本,构建工具版本和构建/编译选项相同,我仍然可以想到许多 可能 的差异来源:
时间戳-类文件可能包含编译时间戳1。除非您在完全相同的时间运行编译,否则同一文件的不同编译将导致不同的时间戳。
源文件名路径-每个类文件都包含源文件的路径名。如果编译两个具有不同路径名的树,则类文件将包含不同的源路径名。
导入的编译时常数的值-当一个类
A
使用在另一个类中定义的编译时常数时B
(请参阅JLS以获取“编译时常数”的定义),该常数的值将合并到A
s类文件中。因此,如果您A
针对不同版本的B
(使用不同的常量值)进行编译,则的代码A
可能会有所不同。由于编译器
identityHashpre
在HashMap
键中使用的差异可能会在某些步骤中导致映射迭代顺序的差异。这可能.class
以不重要的方式影响文件生成,但仍显示为.class
文件差异。例如,常量池条目可能以不同的顺序结束。外部类/方法的签名差异;例如,如果您在一个POM文件中更改了依赖性版本。
有效构建类路径中的差异可能会导致找到导入类的顺序不同。反过来,这可能会导致类文件的“常量池”中条目的顺序发生非重大差异。发生这种情况的原因可能是:
- 文件在外部JAR文件的目录中以不同的顺序出现,
- 由于构建工具迭代源文件时,源文件的顺序不同,因此文件的编译顺序也不同2,或者
- 构建中的并行性(如果已启用)。
对于文件排序问题,有一种可能的解决方法:
-XDsortfiles如JDK-7003006中所述,使用未记录的选项。(对于@Holger知道这一点,表示感谢。)
请注意,您通常不会在文件系统目录中看到文件的实际顺序。命令行工具(例如
ls和和
dir)以及文件浏览器通常会在显示条目之前(以名称或时间戳顺序)对其进行排序。
1-这取决于编译器。另外,也不能保证
javap会显示时间戳…如果存在的话。
2-操作系统不保证列出目录(在syscall级别)将以确定的顺序…或相同的顺序返回文件系统对象(如果已删除并重新添加文件)。
我应该补充说,找出造成差异的原因的第一步是准确找出差异的原因。您可能需要(需要)以困难的方式做到这一点-
通过手动解码一对类文件来识别它们实际存在差异的位置以及差异的实际含义。



