我知道 Microsoft .NET 使用 CLR 作为 JIT 编译器,而 Java 有 Hotspot。它们之间有什么区别?
1 回答
他们是非常不同的野兽。正如人们所指出的,CLR 在执行一段 MSIL 之前会编译为机器代码。除了典型的死代码消除和内联私有优化之外,这还允许它利用目标机器的特定 CPU 架构(尽管我不确定它是否这样做)。这也会对每个类产生影响(尽管编译器相当快,而且许多平台库只是 Win32 API 上的一个薄层)。
HotSpot VM 采用了不同的方法。它规定大部分代码很少执行,因此不值得花时间编译它。所有字节码都以解释模式开始。VM 在调用点保留统计信息,并尝试识别调用次数超过预定义次数的方法。然后它使用快速 JIT 编译器 (C1) 仅编译这些方法,并在其运行时交换方法(这是 HS 的特殊酱汁)。在 C1 编译的方法被调用多次后,同样的方法会被慢速但复杂的编译器编译,并且代码会在运行中再次交换。
由于 HotSpot 可以在运行时交换方法,因此 VM 编译器可以执行一些在静态编译代码中不安全的推测优化。一个典型的例子是单态调用的静态调度/内联(只有一个实现的多态方法)。如果 VM 发现此方法始终解析为相同的目标,则执行此操作。过去复杂的调用被简化为几个 CPU 指令保护,这些指令由现代 CPU 预测和流水线化。当保护条件不再为真时,VM 可以采用不同的代码路径,甚至退回到解释模式。根据统计数据和程序工作量,生成的机器代码在不同的时间可能会有所不同。
这就是为什么在对算法进行基准测试时需要预热 JVM 并模拟真实的工作负载(倾斜的数据可能导致对优化的评估不切实际)。其他优化有锁省略、自适应自旋锁定、逃逸分析和堆栈分配等。
也就是说,HotSpot 只是其中一种虚拟机。JRockit、Azul、IBM 的 J9 和 Resettable RVM——都有不同的性能配置文件。