作为MSIL和Java字节码之间的差异问题的一种跟进?,Java虚拟机的工作方式(主要)差异或相似之处是什么?.NET Framework 公共语言运行时(CLR)有效吗?
还有,是 .NET框架 CLR是"虚拟机"还是没有虚拟机的属性?
两种实现之间有很多相似之处(在我看来:是的,它们都是"虚拟机").
首先,它们都是基于堆栈的VM,没有"寄存器"的概念,就像我们习惯于在x86或PowerPC等现代CPU中看到的那样.所有表达式((1 + 1)/ 2)的评估是通过将操作数推入"堆栈"然后在指令(加,除等)需要消耗这些操作数时从堆栈中弹出这些操作数来执行的.每条指令将其结果推回堆栈.
这是实现虚拟机的一种便捷方式,因为世界上几乎每个CPU都有一个堆栈,但寄存器的数量通常不同(有些寄存器是专用的,每个指令都要求它的操作数在不同的寄存器中等等).
因此,如果您要为抽象机器建模,那么纯粹基于堆栈的模型是一种非常好的方法.
当然,真正的机器不能以这种方式运行.因此,JIT编译器负责执行字节码操作的"注册",实质上是调度实际的CPU寄存器以尽可能包含操作数和结果.
所以,我认为这是CLR和JVM之间最大的共性之一.
至于差异......
这两种实现之间的一个有趣的区别是CLR包含用于创建泛型类型的指令,然后用于将参数化特化应用于这些类型.因此,在运行时,CLR认为List
在封面下,它对所有引用类型的特化使用相同的MSIL(因此List
在Java中,泛型类型纯粹是一种编译器技巧.JVM没有关于哪些类具有类型参数的概念,并且它无法在运行时执行参数化特化.
从实际角度来看,这意味着您不能在泛型类型上重载Java方法.您不能使用具有相同名称的两种不同方法,区别在于它们是接受List
在日常的基础上,这是我在CLR和JVM之间最常见的区别.
其他重要的差异包括:
CLR有闭包(实现为C#代理).自Java 8以来,JVM仅支持闭包.
CLR具有协同程序(使用C#'yield'关键字实现).JVM没有.
CLR允许用户代码定义新的值类型(结构),而JVM提供固定的值类型集合(byte,short,int,long,float,double,char,boolean),并且只允许用户定义新的引用 - 类型(类).
CLR支持声明和操作指针.这一点特别有趣,因为JVM和CLR都采用严格的代压缩垃圾收集器实现作为其内存管理策略.在通常情况下,严格压缩GC的指针非常困难,因为当您将值从一个内存位置移动到另一个内存位置时,所有指针(和指针指针)都将变为无效.但是CLR提供了一种"固定"机制,以便开发人员可以声明一个代码块,在该代码块内不允许CLR移动某些指针.这很方便.
JVM中最大的代码单元是"包",可以通过'protected'关键字或可以说是JAR(即Java ARchive)来证明,这可以通过在类路径中指定jar并将其视为文件夹来证明代码 在CLR中,类被聚合到"程序集"中,CLR提供用于推理和操作程序集的逻辑(它们被加载到"AppDomains"中,为内存分配和代码执行提供子应用程序级沙箱).
CLR字节码格式(由MSIL指令和元数据组成)具有比JVM更少的指令类型.在JVM中,每个独特的操作(添加两个int值,添加两个浮点值等)都有自己独特的指令.在CLR中,所有MSIL指令都是多态的(添加两个值),JIT编译器负责确定操作数的类型并创建适当的机器代码.不过,我不知道哪个是优选策略.两者都有权衡.用于JVM的HotSpot JIT编译器可以使用更简单的代码生成机制(它不需要确定操作数类型,因为它们已经在指令中编码),但这意味着它需要更复杂的字节码格式,更多指令类型.
我已经使用Java(并欣赏JVM)已有十年了.
但是,在我看来,CLR现在几乎在所有方面都是优秀的实现.
您的第一个问题是将JVM与.NET Framework进行比较 - 我假设您实际上打算与CLR进行比较.如果是这样,我想你可以写一本关于此的小书(编辑:看起来像Benji已经有了:-)
一个重要的区别是,与JVM不同,CLR被设计为与语言无关的架构.
另一个重要的区别是CLR专门设计用于实现与本机代码的高度互操作性.这意味着CLR必须在访问和修改本机内存时管理可靠性和安全性,并且还管理基于CLR的数据结构和本机数据结构之间的编组.
为了回答你的第二个问题,术语"虚拟机"是硬件世界中较早的术语(例如,IBM在20世纪60年代对360的虚拟化),这些术语过去是指底层机器的软件/硬件仿真,以实现相同的类型. VMWare的功能.
CLR通常被称为"执行引擎".在这种情况下,这是在x86之上的IL机器的实现.这也是JVM的作用,尽管你可以说CLR的多态字节码和JVM的类型字节码之间存在重要差异.
所以对你的第二个问题的迂腐回答是"不".但这实际上取决于你如何定义这两个术语.
编辑: JVM和CLR之间的另一个区别是JVM(版本6)非常不愿意将已分配的内存释放回操作系统,即使它可以.
例如,假设JVM进程最初启动并从操作系统分配25 MB内存.然后,应用程序代码尝试分配需要额外50 MB的分配.JVM将从操作系统分配额外的50 MB.一旦应用程序代码停止使用该内存,它就会被垃圾收集,并且JVM堆大小将减少.但是,JVM只会在某些特定情况下释放分配的操作系统内存.否则,对于剩余的进程生命周期,内存将保持分配状态.
另一方面,如果不再需要CLR,则将已分配的内存释放回操作系统.在上面的示例中,一旦堆减少,CLR就会释放内存.
可以从各种学术和私人来源找到关于差异的更多细节.CLR设计选择就是一个很好的例子.
一些具体的例子包括:
一些低级别的opperands被输入,例如"添加两个整数",其中CLR使用多态操作数.(即fadd/iadd/ladd vs just add)
目前,JVM进行更具侵略性的运行时分析和优化(即Hotspot).CLR目前进行JIT优化,但不进行运行时优化(即在运行时替换代码).
CLR没有内联虚拟方法,JVM确实......
支持CLR中的值类型,而不仅仅是"原语".
CLR和JVM都是虚拟机.
.NET Framework和Java运行时环境是各个VM及其库的捆绑.没有库,虚拟机就没用了.