是CLR虚拟机?(Is the CLR a virtual machine?)

2019-07-23 14:01发布

我读了一本书,其中提到了.NET CLR作为虚拟机 ? 任何人都可以证明这一点? 什么是我们所需要的虚拟机上的一些开发平台概念的原因吗?

是不是可以开发是完全面向对象和强大的.NET本地框架[一个没有虚拟机]?

这是指CLR虚拟机本书是“ 专业.Net框架2.0”。

Answer 1:

这里有很多误解。 我想你能想到的.NET作为一个虚拟机,如果你真的想,但是让我们看看在.Net框架到底是如何处理你的代码。 典型的情况是这样的

  1. 你写在C#,VB.Net,F#,或一些其他兼容的语言。净程序。
  2. 即代码被编译成中间语言(IL),其类似于Java的字节码,即分配给最终用户的机器。
  3. 最终用户调用首次程序安装的.Net的正确版本的计算机上
  4. 计算机认为这是一个.NET组件,而不是“原始”机器代码,并将其关闭,以JIT编译器
  5. JIT编译器编译IL完全本地机器代码
  6. 本机代码保存在存储器中的这个程序执行的寿命。
  7. 保存的本地代码调用,而IL不再是问题。

有几个重要的点,在这里,但大的一个是,在任何时候,任何代码曾经解释。 相反,你可以在步骤5中看到,它被编译为本地代码。 这比直接装载到虚拟机,有几个原因的巨大差异:

  1. 完全编译的代码由CPU直接执行的,而不是解释或翻译的一个额外的软件抽象层,这应该是更快。
  2. JIT编译器可以运行程序,而不是满足于最小公分母具体到个人机最优化的优势。
  3. 如果你愿意,你甚至可以完全预编译来自用户的代码,并在本质上隐藏第5步。

我想你可以称这是一个虚拟机,在这个意义上的抖动从开发商抽象了的真机细节。 我个人不认为这是很合适的,因为对许多人来说,虚拟机意味着运行时间抽象来自对.NET程序并不存在本地代码了

这整个过程中的一个另一个重点是真的,它除了从“虚拟机”的环境,这只是典型的过程。 如果你真的想,你可以在分发之前预编译.NET程序集,并直接部署本地代码到最终用户(提示:这是在聚集在程序的生命慢,因为你失去的特定机器优化)。 当然,你还需要安装.NET运行时,但在这一点上它确实没有太大的任何其他运行时API不同; 它更像是一个不错的API,你可以对链接的集合的dll,你可能已经用VB或C运行微软还附带与Visual Studio。 那种这需要的IL出来的画面,使得VM绰号更难自圆其说。 (我说“种”,因为IL仍部署和使用验证码保存,但它从来没有自己感动执行)。

另外一个有说服力的一点是缺乏一个VM的过程。 当你运行你的应用程序,有运行没有共同的“沙箱”的过程。 与Java,在那里,如果你打开程序的情况下运行,你会看到具体过程为Java虚拟机的任务管理器比较一下,和应用程序的实际过程是由虚拟机创建的沙箱中的一个线程。 在.NET中,你看到的应用程序直接在Windows任务管理器进程。

总结:可以说,IL + CLR + JIT一起某种程度上构成了一个虚拟机。 我个人不这么认为,但我不会跟你争论,如果你相信这一点。 我想指出的一点是,当你告诉别人的.Net运行在一个虚拟机,没有进一步的解释,你在传输到该人的理念是“在主机进程解释字节码。” 而这仅仅是错误的。



Answer 2:

类似于Java虚拟机(JVM)的.NET CLR是一个字节码解释虚拟机。

JVM解释包含Java字节码和.NET CLR解释包含微软称之为“中间语言(IL)”的指令程序的程序。 有这些字节代码之间的差异,但虚拟机都差不多,向往来提供类似的功能。

这两个虚拟机实现的需要编译的字节代码输入到他们正在运行的计算机的机器语言的能力。 这被称为“即时编译(JIT)”和产生的输出代码被称为“JIT代码。” 因为JIT代码包含在计算机的CPU的机器语言指令序列,该代码是有时被称为“本机”代码。

然而,JIT代码是定性和从本机代码定量不同,如下面所解释。 因此,本文认为JIT代码只不过是一个本地实现虚拟机的多个运行特定字节码程序的同时

一个功能,这两个虚拟机(VM)的向往,以提供对预防某些有害程序错误形式的安全性。 例如,该网站论坛的标题,计算器,由一个这种类型的危险的错误是可能在本机代码的启发。

为了提供安全性和执行的安全性,实现虚拟机在“虚拟机级别”类型安全。 分配给VM存储器中要求存储其在该存储位置中保存的数据的类型。 例如,如果整数被压入堆栈,这是无法从栈中弹出一个两倍。 C风格的“工会”被禁止。 指针和直接访问内存是禁止的。

如果结果是一个本地二进制,如EXE文件,我们无法通过强制开发商面向对象语言的框架得到同样的好处。 在这种情况下,我们将无法使用通过采用比框架其它来源的恶意用户生成的框架和EXE文件生成本地二进制代码来区分。

在虚拟机的情况下,类型安全的程序员被允许访问“最低水平”执行。 (忽略了片刻,这是可能写管理的本机码,即)。因此,任何用户都会遇到其执行其需要到存储器位置和指针直接访问危险操作中的一个的应用程序。

在实践中,.NET CLR实现方式编写原生代码可通过.NET“托管”代码调用。 在这种情况下,负担是本机代码的作者不作任何指针和内存错误。

由于JVM和.NET CLR进行JIT编译,无论是虚拟机实际上创建从所提供的字节码的本地编译的二进制。 这种“JIT代码”进行比对虚拟机的解释执行得更快,因为即使通过JIT生产的机器语言代码包含了所有的虚拟机所需要的安全检查,该虚拟机将执行。 其结果是,在JIT输出代码是不一样快,原生代码,通常会不含有大量的运行时检查。 然而,这样的速度性能的缺点是用于改进可靠性包括安全交换; 特别是,可以防止使用未初始化的存储的,指配的类型安全强制执行,范围检查被执行(从而重新建立了新和溢出防止按堆基于缓冲液),对象的寿命是由垃圾收集管理,动态分配是类型安全的。 执行这样运行时行为检查的环境中实现虚拟机的规格,比机器语言实现了虚拟机的多一点。



Answer 3:

“虚拟机”部分指的是事实,.NET代码被编译成exe和DLL的为“中级”汇编语言(IL)在虚拟机上运行,​​而不是真正的CPU汇编语言。 然后,在运行时ILM转换成用于执行真实CPU组件(称为刚刚在时间,或JIT编译)。

当然,你可以写一个.NET编译,这样它会被编译成CPU汇编语言,而不是IL。 然而,这不会是移植到所有的CPU - 你必须编译每个OS / CPU对不同的版本。 但是,通过编译成ILM,你让“虚拟机”处理CPU和OS具体的东西。



Answer 4:

我有点老派,所以我称之为CLR虚拟机也是如此。 我的理由是,CLR从中间字节码,这是一个虚拟机也做组装的机器代码。

CLR的好处主要是由于它装配了利用运行时类型信息的机器代码的方式。

你可以发展成为只使用本地类型的.NET框架作为一个强大的本地框架。 你失去了唯一的灵活性是重组原生代码,如果你曾经运送程序到另一个平台而无需重新编译的能力。



Answer 5:

CLR的优势是写在任何编程语言的开发者选择的代码,因为代码会被解释为本地调用之前被编译到CLR的自由。 .NET框架使用这个JIT编译对待这对于平台的工作部署上的一切均匀输出方案,这是由编译语言缺席。



Answer 6:

无论是JVM还是CLR做任何事情比什么最“虚拟机”用于其他语言也做重大差异。 现代化的,它们都使用JIT转换虚拟指令(P码,字节码,中间语言指令,把它不管你喜欢)的“本地CPU硬件”指令(“机器代码”。)

事实上,第一个“虚拟机”要做到这一点是Smalltalk的虚拟机。 创新的作者彼得德语,戏称其“动态转换”,而不是这是由Java的普及“JIT”一词。 如果Smalltalk的“运行时执行环境”将被称为“虚拟机”(而这正是它仍然呼吁,),那么做任何和所有其他“运行时系统”本质上是相同的事情也有资格作为“虚拟机。 “



Answer 7:

你有许多有价值的答案,但我认为有一件事还没有被提及:模块化。

这是相当难以从本地DLL导出一个OO类。 当然,你可以告诉链接导出类和导入其他地方,但这是脆; 在一个类中改变一个私有成员将打破二进制兼容,也就是说,如果你改变一个DLL而无需重新编译所有其他模块,你的程序在运行时将可怕崩溃。

周围有这样一些方法:例如,你可以定义公共抽象接口,从这些出口全球工厂函数从DLL导出。 这样一来,你可以改变一个类的实现细节。 但你不能从其他DLL中类派生。 而改变接口也打破当然二进制兼容性。

我不知道是否有在本地代码这是一个很好的解决方案:如果编译器/连接器在编译时创建的本地代码,那么它必须知道,在代码中使用的类/结构的精确内存布局。 如果最后的统计处理(生成本地代码)被延迟,直到一个方法被调用的第一次,这个问题简单地消失了:你可以修改类的组件,并且只要JIT可以解决所有使用的成员运行时 ,一切都会运行良好。

简而言之:如果您创建一个单片单的可执行程序,你很可能有大部分的.NET的强大功能与创建本机代码的编译器。 但有一个JIT编译器(框架安装,稍长的启动时间)的缺点实在不超过在大多数情况下的好处。



文章来源: Is the CLR a virtual machine?