java机器码在相同的硬件上会相同吗?
我知道 java 源代码将被编译为字节码,JVM 将解释该字节码并将其转换为底层平台的本地机器代码。
但是我想知道如果我有一台 x86 机器,无论我选择安装哪个操作系统,由平台相关的 JVM 翻译的机器代码是否相同?
回答
TL; DR - 不,不会。
JIT 编译器从相同的字节码、相同的 Java 版本和相同的操作系统生成的本机代码仍然可能不同。
-
生成的代码可能取决于运行 JVM 的物理硬件;例如内核数量、芯片组等。
-
生成的代码甚至可能取决于程序的输入。在 JIT 编译之前,JVM 使用字节码解释器来运行代码。这种自我分析收集有关分支概率等的统计信息。这些统计信息由 JIT 优化器使用。由于运行程序时所采用的代码路径可能取决于程序输入,因此同一程序在同一台机器上的不同运行可能最终导致 JIT 编译器生成不同的本机代码。
-
由于 JVM 预热期间的非确定性行为会影响自分析期间收集的统计信息,因此生成的代码甚至可能在具有相同输入的相同平台上运行相同代码时有所不同。
这就是 HotSpot JIT 编译的好处。它适应环境以及应用程序的功能。但是,如果您的主要目标是获得可重现的本机代码和可重现的性能特征,这可能是一个问题。
- The self-profiling, e.g. to determine the hot spots, depends on the timing that can be subtle in some scenarios. So I’d not only say, that the generated code may change with the system load, it may even differ spuriously, without an obvious cause. Some compilation tasks run concurrently to the application threads (and other processes on the same machine), so their progress can be influenced by them, which in turn influences later compilation decisions (e.g. a slowdown in one task may make more meta information available for the next one).
- There are typically more than one JIT compiler threads (at least, one C1 and one C2), and they work in background. Since timings are not determenistic, the compilation order may differ, and so may the generated code (as it depends on many factors, including the runtime profile, the compilation history, the length of compilation queues etc.) I've seen many times, especially on microbenchmarks, that the generated code differs from run to run, even without notable change in the system load.