首先,它们都是基于堆栈的 VM,没有我们在现代 CPU (如 x86或 PowerPC)中常见的“寄存器”概念。对所有表达式((1 + 1)/2)的求值是通过将操作数推到“堆栈”上,然后在指令(添加、除法等)需要使用这些操作数时将这些操作数从堆栈中弹出来来执行的。每条指令都将其结果推回到堆栈上。
这是实现虚拟机的一种方便的方法,因为世界上几乎每个 CPU 都有一个堆栈,但寄存器的数量通常是不同的(有些寄存器是特殊用途的,每条指令需要在不同的寄存器中使用其操作数,等等)。
所以,如果你要建模一个抽象机器,一个纯粹的基于堆栈的模型是一个很好的方法。
当然,真正的机器不是这样运作的。因此,JIT 编译器负责执行字节码操作的“注册”,实际上是调度实际的 CPU 寄存器,以便在可能的情况下包含操作数和结果。
因此,我认为这是 CLR 和 JVM 之间最大的共同点之一。
至于分歧..。
这两种实现之间一个有趣的区别在于,CLR 包含了创建泛型类型的指令,然后还包含了对这些类型应用参数化的指令。因此,在运行时,CLR 将 List < int > 视为与 List < String > 完全不同的类型。
在底层,它对所有引用类型专门化使用相同的 MSIL (因此 List < String > 使用与 List < Object > 相同的实现,在 API 边界使用不同的类型转换) ,但是每个值类型使用自己独特的实现(List < int > 生成与 List < double > 完全不同的代码)。