作为对MSIL和Java字节码之间差异的问题的一种跟进?,Java虚拟机的工作方式与Java虚拟机的主要(主要)区别或相似之处是什么.NET Framework 公共语言运行库(CLR)是否有效?
另外,是 .NET框架 CLR是“虚拟机”还是不具有虚拟机的属性?
作为对MSIL和Java字节码之间差异的问题的一种跟进?,Java虚拟机的工作方式与Java虚拟机的主要(主要)区别或相似之处是什么.NET Framework 公共语言运行库(CLR)是否有效?
另外,是 .NET框架 CLR是“虚拟机”还是不具有虚拟机的属性?
Answers:
两种实现之间有很多相似之处(我认为:是的,它们都是“虚拟机”)。
一方面,它们都是基于堆栈的VM,没有“寄存器”的概念,就像我们过去经常在x86或PowerPC这样的现代CPU中看到的那样。通过将操作数推入“堆栈”,然后每当一条指令(加法,除法等)需要使用这些操作数时,将这些操作数从堆栈中弹出,即可对所有表达式((1 + 1)/ 2)求值。每条指令将其结果压回堆栈。
这是一种实现虚拟机的简便方法,因为世界上几乎每个CPU都有一个堆栈,但是寄存器的数量通常是不同的(某些寄存器是专用的,每个指令期望其操作数位于不同的寄存器中,依此类推。 )。
因此,如果您要对抽象机进行建模,那么纯粹基于堆栈的模型是一个很好的选择。
当然,真正的机器不会以这种方式运行。因此,JIT编译器负责执行字节码操作的“注册”,实质上是尽可能地调度实际的CPU寄存器以包含操作数和结果。
因此,我认为这是CLR和JVM之间最大的共性之一。
至于差异...
两种实现之间的一个有趣的区别是,CLR包含用于创建泛型类型,然后将参数专业化应用于这些类型的指令。因此,在运行时,CLR认为List <int>与List <String>是完全不同的类型。
在幕后,它对所有引用类型特化使用相同的MSIL(因此List <String>使用与List <Object>相同的实现,在API边界具有不同的类型转换),但是每种值类型使用它自己的独特实现(List <int>生成与List <double>完全不同的代码)。
在Java中,泛型是纯粹的编译技巧。JVM不知道哪些类具有类型参数,并且无法在运行时执行参数专用化。
从实际的角度来看,这意味着您不能在泛型类型上重载Java方法。您不能有两个具有相同名称的不同方法,仅在它们接受List <String>或List <Date>方面有所不同。当然,由于CLR知道参数类型,因此它没有在通用类型专门化方面重载的问题处理方法。
每天,这是我在CLR和JVM之间最明显的区别。
其他重要区别包括:
CLR具有闭包(作为C#委托实现)。JVM仅从Java 8开始才支持闭包。
CLR具有协程(通过C#'yield'关键字实现)。JVM没有。
CLR允许用户代码定义新的值类型(结构),而JVM提供固定的值类型集合(字节,短型,整型,长型,浮点型,双精度型,字符型,布尔型),并且仅允许用户定义新的引用-类型(类)。
CLR提供了声明和操作指针的支持。这特别有趣,因为JVM和CLR均采用严格的世代压缩垃圾收集器实现作为其内存管理策略。在通常情况下,严格的压缩GC很难使用指针,因为将值从一个存储位置移动到另一个存储位置时,所有指针(和指向指针的指针)都将变为无效。但是CLR提供了一种“固定”机制,以便开发人员可以声明一个代码块,在其中不允许CLR移动某些指针。非常方便
JVM中最大的代码单元是“保护”关键字所证明的“包”,或者是能够在类路径中指定jar并将其像文件夹一样证明的JAR(即Java ARchive)。代码。在CLR中,类被聚合为“程序集”,而CLR提供推理和操纵程序集的逻辑(程序集被加载到“ AppDomains”中,提供子应用程序级沙箱用于内存分配和代码执行)。
CLR字节码格式(由MSIL指令和元数据组成)具有比JVM少的指令类型。在JVM中,每个唯一操作(添加两个int值,添加两个float值等)都有自己的唯一指令。在CLR中,所有MSIL指令都是多态的(加两个值),而JIT编译器负责确定操作数的类型并创建适当的机器代码。我不知道哪个是最好的策略。两者都有权衡。适用于JVM的HotSpot JIT编译器可以使用更简单的代码生成机制(它不需要确定操作数类型,因为它们已经在指令中编码了),但这意味着它需要更复杂的字节码格式,具有更多指令类型。
我已经使用Java(并欣赏JVM)已有大约十年了。
但是,我认为,几乎在所有方面,CLR都是卓越的实现。
您的第一个问题是将JVM与.NET Framework进行比较-我假设您实际上是要与CLR进行比较。如果是这样,我想您可以为此写一本小书(编辑:看来Benji已经有了:-)
一个重要的区别是,与JVM不同,CLR被设计为与语言无关的体系结构。
另一个重要的区别是,CLR是专门为允许与本机代码实现高度互操作性而设计的。这意味着在访问和修改本机内存时,CLR必须管理可靠性和安全性,并且还必须管理基于CLR的数据结构与本机数据结构之间的编组。
为了回答您的第二个问题,术语“虚拟机”是硬件世界中的一个较旧术语(例如,IBM在1960年代对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和JVM都是虚拟机。
.NET Framework和Java运行时环境是各个VM及其库的捆绑。没有库,虚拟机将毫无用处。
可以从各种学术和私人来源中找到有关差异的更多详细信息。一个很好的例子就是CLR Design Choices。
一些具体示例包括:
它不是虚拟机,.net框架在第一次运行时将程序集编译为本地二进制文件:
在计算中,即时编译(JIT)(也称为动态翻译)是一种用于提高计算机程序的运行时性能的技术。JIT基于运行时环境中的两个较早的想法:字节码编译和动态编译。它在本地执行代码之前先在运行时将其转换,例如将字节码转换为本地机器代码。与解释器相比,性能的提高源自缓存代码块翻译的结果,而不是每次遇到行或操作数时都要重新评估(请参见解释性语言)。与在开发时静态编译代码相比,它还具有优势,因为如果发现这样做是有利的,它可以重新编译代码,并且可以执行安全保证。
几种现代的运行时环境,例如Microsoft的.NET Framework,大多数Java实现以及最近的Actionscript 3,都依赖JIT编译来执行高速代码。
资料来源:http : //en.wikipedia.org/wiki/Just-in-time_compilation
像Java一样,添加.NET框架包含一个虚拟机。