Java的虚拟机和CLR

问题描述:

作为对Differences between MSIL and Java bytecode?这个问题的一种跟进,在Java虚拟机的工作方式与公共语言运行时间(CLR)之间有什么(主要)区别或相似之处,作品? CLR是一个“虚拟机”,还是它没有虚拟机的属性?是否是“虚拟机”还是不具有虚拟机的属性?Java的虚拟机和CLR

+0

那么,如果你比较喜欢和喜欢,你应该把这个问题作为虚拟机和CLR(公共语言运行时间)之间的差异来重新解释,这是VM的直接模拟。 – cletus 2009-01-17 17:11:19

+1

签出:[CLR元数据神话在托管模块?](http://izlooite.blogspot.com/2009/09/what-is-clr-metadata-in-managed-module.html#more) – 2011-03-23 17:17:56

+18

@Truth,您已将此问题链接到自身...... – 2013-06-11 19:10:26

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

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

这是一种实现虚拟机的方便方法,因为世界上几乎每个CPU都有一个堆栈,但寄存器的数量通常是不同的(有些寄存器是特殊用途的,每个指令都希望其操作数在不同的寄存器等)。所以,如果你打算建立一个抽象机器的模型,那么一个纯粹的基于堆栈的模型是一个相当不错的方法。

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

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

至于差异...

一个有趣的区别是,CLR包括用于创建泛型类型的指令,然后将参数专门化的类型。因此,在运行时,CLR认为列表<int>是与列表<字符串>完全不同的类型。

在内部,它使用的所有参考型专业化相同MSIL(这样一个列表<字符串>使用相同的实现作为List <对象>,具有不同类型强制转换在API边界),但是每个值类型使用其自己独特的实现(列表<int>生成完全不同的代码从列表<双>)。

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

从实践的角度来看,这意味着您不能在泛型类型上重载Java方法。您不能有两种不同的方法,名称不同,只有它们接受列表<字符串>或列表<日期>。当然,由于CLR知道参数类型,所以在泛型专业化上没有问题的处理方法被重载。

在日常工作中,我注意到CLR和JVM之间最大的不同。

其他重要的不同之处包括:

  • 的CLR封了(如C#委托实现)。 JVM自Java 8以来才支持闭包。

  • CLR具有协同程序(使用C#“yield”关键字实现)。 JVM不。 (CLR)允许用户代码定义新的值类型(结构),而JVM提供了一个固定的值类型集合(byte,short,int,long,float,double,char,boolean),并且只允许用户定义新的参考类型(类)。

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

  • 的代码在JVM的最大的单位是通过能够在类路径specifiy一个罐子证明,并具有就证明了“保护”的关键字或可以说是一个JAR(即Java归档)或者是“包”它像一个代码文件夹对待。在CLR中,类被聚合成'程序集',并且CLR提供用于推理和操作程序集(被加载到“AppDomain”中,为内存分配和代码执行提供子应用程序级沙箱)的逻辑。

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

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

但是,在我看来,CLR现在几乎在所有方面都是上级实施。

CLR和JVM都是虚拟机。

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

它不是一个虚拟机,.NET框架编译组件插入机二进制在第一运行时间:

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

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

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

加起来.NET框架包含的虚拟机,这与Java一样。

+10

仅仅因为虚拟机利用JIT进行性能优化并不意味着它不再是虚拟机。当程序员编译他编译到虚拟机时,留给执行执行,但它看起来合适 – 2009-01-17 18:47:58

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

的一个重要区别是,CLR被设计为一个中性语言体系结构,不同的是JVM 。

另一个重要的区别是,CLR是专门设计用于与本机代码实现高水平的互操作性。这意味着当本地内存被访问和修改时,CLR必须管理可靠性和安全性,并且还要在基于CLR的数据结构和本机数据结构之间管理可靠性和安全性。

要回答第二个问题,术语“虚拟机”是来自硬件世界的旧术语(例如IBM在20世纪60年代的360的虚拟化),过去这意味着要完成底层机器的软件/硬件仿真与VMware相同的东西。

CLR通常被称为“执行引擎”。在这种情况下,这是一个在x86之上的IL机器的实现。这也是JVM所做的,尽管您可以争辩说CLR的多态字节码与JVM的键入字节码之间存在重要区别。

因此,对第二个问题的迂回回答是“不”。但是真正归结为你如何定义这两个术语。

编辑: JVM和CLR之间的一个更差的是,JVM(第6版)是very reluctant以释放分配的内存回给操作系统,即使在它可以。

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

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

关于差异的更多细节可以从各种学术和私人来源中找到。一个很好的例子是CLR Design Choices

一些具体实例包括:

  • 一些低级别opperands被键入诸如“添加两个int”,其中作为CLR使用一个多态操作数。 (即fadd/iadd/ladd vs只是添加)
  • 目前,JVM执行更多攻击性运行时分析和优化(即热点)。 CLR目前进行JIT优化,但不是运行时优化(即在运行时替换代码)。
  • CLR不内联虚拟方法,JVM不支持...
  • 支持CLR中的值类型,而不仅仅是“基元”。