Java的虚拟机和CLR

作为一种跟进称为MSIL和Java字节码之间差异的问题? Java虚拟机如何工作与如何工作有什么(主要)差异或相似之处 .NET Framework 公共语言运行时(CLR)的作品?

另外,是 .NET框架 CLR是“虚拟机”还是没有虚拟机的属性?

这两个实现之间有很多相似之处(在我看来:是的,他们都是“虚拟机”)。

首先,它们都是基于堆栈的虚拟机,没有“寄存器”的概念,就像我们习惯于在x86或PowerPC等现代CPU中看到的一样。 所有expression式((1 + 1)/ 2)的求值是通过将操作数推入“堆栈”,然后在指令(加法,除法等)需要消耗这些操作数时从堆栈中popup这些操作数来执行的。 每条指令都将结果推回堆栈。

这是一个实现虚拟机的简便方法,因为世界上几乎每个CPU都有一个堆栈,但是寄存器的数量往往是不同的(有些寄存器是专用的,每个指令都要求其操作数在不同的寄存器等等)。

所以,如果你要模拟一个抽象机器,一个纯粹的基于堆栈的模型是一个很好的方法。

当然,真正的机器不这样操作。 所以JIT编译器负责执行字节码操作的“登记”,实际上调度实际的CPU寄存器以尽可能地包含操作数和结果。

所以,我认为这是CLR和JVM之间最大的共同点之一。

至于差异…

这两个实现之间的一个有趣的区别是,CLR包含创buildgenericstypes的指令,然后为这些types应用参数化特化。 因此,在运行时,CLR认为List <int>是与List <String>完全不同的types。

在封面下,它对所有的引用types特化使用相同的MSIL(所以List <String>使用与List <Object>相同的实现,在API边界使用不同的types转换),但是每个值types使用它自己的唯一实现(List <int>生成与List <double>完全不同的代码)。

在Java中,genericstypes纯粹是一种编译器技巧。 JVM没有关于哪些类具有types参数的概念,并且在运行时无法执行参数化特化。

从实际的angular度来看,这意味着你不能在genericstypes上重载Java方法。 你不能有两个不同的方法,只有它们接受一个List <String>或一个List <Date>,才会有相同的名称。 当然,因为CLR知道参数types,所以在通用types专业化上重载的处理方法没有问题。

在日常的基础上,这是CLR和JVM之间最大的差异。

其他重要差异包括:

  • CLR已closures(作为C#代理实现)。 JVM自Java 8以来才支持闭包。

  • CLR具有协同程序(用C#“yield”关键字实现)。 JVM不。

  • CLR允许用户代码定义新的值types(结构),而JVM提供了一个固定的值types集合(byte,short,int,long,float,double,char,boolean),只允许用户定义新的参考 – types(类)。

  • CLR提供了对声明和操作指针的支持。 这是特别有趣的,因为JVM和CLR都使用严格的代性压缩垃圾收集器实现作为其内存pipe理策略。 在一般情况下,严格压缩GC的指针非常困难,因为当你将一个值从一个存储单元移到另一个存储单元时,所有的指针(和指向指针的指针)都会失效。 但是CLR提供了一种“固定”机制,因此开发人员可以声明一个代码块,在这个代码块中不允许CLR移动某些指针。 这很方便。

  • JVM中最大的代码单元是由'protected'关键字certificate的“包”,或者可以说是JAR(即Java归档),如能够在类path中指定一个jar并将其视为一个文件夹的代码。 在CLR中,类被聚合成“程序集”,CLR提供逻辑推理和操作程序集(加载到“AppDomain”中,为内存分配和代码执行提供子应用程序级别的沙箱)。

  • CLR字节码格式(由MSIL指令和元数据组成)具有比JVM更less的指令types。 在JVM中,每个独特的操作(添加两个int值,添加两个浮点值等)都有自己独特的指令。 在CLR中,所有MSIL指令都是多态的(添加两个值),JIT编译器负责确定操作数的types并创build适当的机器码。 不过,我不知道哪个是最好的策略。 两者都有权衡。 用于JVM的HotSpot JIT编译器可以使用更简单的代码生成机制(不需要确定操作数types,因为它们已经被编码在指令中),但是这意味着它需要更复杂的字节码格式,更多的指令types。

我一直在使用Java(并欣赏JVM)大约十年了。

但是,在我看来,CLR现在几乎在所有方面都是优秀的实现。

你的第一个问题是将JVM与.NET Framework进行比较 – 我假设你实际上是想和CLR进行比较。 如果是这样,我想你可以写一本小书( 编辑:看起来像Benji已经有:-)

一个重要的区别是,与JVM不同,CLR被devise为与语言无关的架构。

另一个重要的区别是,CLR是专门devise的,以便与本机代码具有高度的互操作性。 这意味着当本地内存被访问和修改时,CLR必须pipe理可靠性和安全性,并且还要pipe理基于CLR的数据结构和本地数据结构之间的编组 。

为了回答第二个问题,术语“虚拟机”是硬件世界中一个较老的术语(例如IBM在二十世纪六十年代对360的虚拟化),过去这个术语是指底层机器的软件/硬件仿真,以完成同样的虚拟机的东西。

CLR通常被称为“执行引擎”。 在这种情况下,这是一个在x86之上的IL机器的实现。 这也是JVM所做的,虽然你可以争辩说CLR的多态字节码和JVM的字节码有很大的区别。

所以第二个问题的迂回答案是“不”。 但是真正归结到你如何定义这两个术语。

编辑: JVM和CLR之间的另一个区别是,JVM(版本6) 非常不愿意将分配的内存释放回操作系统,即使它可以。

例如,假设一个JVM进程从最初的操作系统启动并分配25 MB的内存。 应用程序代码然后尝试分配,需要额外的50 MB。 JVM将从操作系统分配额外的50 MB。 一旦应用程序代码停止使用该内存,它将被垃圾回收,并且JVM堆大小将减less。 但是,JVM只能在特定情况下释放分配的操作系统内存。 否则,对于剩余的进程生命周期内存将保持分配。

另一方面,CLR将分配的内存释放回操作系统(如果不再需要的话)。 在上面的例子中,CLR会在堆减less后释放内存。

CLR和JVM都是虚拟机。

.NET Framework和Java运行时环境是各自的VM及其库的捆绑。 没有库,虚拟机是非常无用的。

有关这些差异的更多细节可以从各种学术和私人来源中find。 一个很好的例子就是CLRdeviseselect 。

一些具体的例子包括:

  • 一些低级操作符是键入的,例如“添加两个整数”,其中CLR使用多态操作数。 (即fadd / iadd / ladd vs只是添加)
  • 目前,JVM执行更多攻击性的运行时分析和优化(即Hotspot)。 CLR目前进行JIT优化,但不是运行时优化(即在运行时replace代码)。
  • CLR不内联虚拟方法,JVM不…
  • 支持CLR中的值types,而不仅仅是“基元”。

它不是一个虚拟机,.net框架在第一次运行的时候将程序集编译成本地二进制文件:

在计算中,即时编译(JIT),也称为dynamic翻译,是一种提高计算机程序运行时性能的技术。 JITbuild立在运行时环境的两个早期思想上:字节码编译和dynamic编译。 它在运行之前将代码转换为本地执行代码,例如将字节代码转换为本地机器代码。 解释器的性能提高来源于caching翻译代码块的结果,而不是每次符合时重新评估每一行或操作数(请参阅解释型语言)。 与开发时静态编译代码相比,它还具有优势,因为如果发现它是有利的,它可以重新编译代码,并且可以执行安全保证。 因此JIT可以结合一些解释和静态(提前)编译的优点。

一些现代的运行时环境,比如Microsoft的.NET Framework,大多数Java的实现,以及最近的Actionscript 3,依靠JIT编译来实现高速代码。

来源: http : //en.wikipedia.org/wiki/Just-in-time_compilation

添加.NET框架包含一个虚拟机,就像Java一样。