2009-01-17 155 views
121

作爲對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

回答

257

這兩個實現之間有很多相似之處(在我看來:是的,它們都是「虛擬機」)。

首先,它們都是基於堆棧的虛擬機,沒有「寄存器」的概念,就像我們習慣在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現在幾乎在所有方面都是上級實施。

9

CLR和JVM都是虛擬機。

.NET框架和Java運行時環境是各自的VM及其庫的捆綁。沒有庫,虛擬機非常無用。

-11

它不是一個虛擬機,.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

24

你的第一個問題是將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會在堆減少後釋放內存。

9

關於差異的更多細節可以從各種學術和私人來源中找到。一個很好的例子是CLR Design Choices

一些具體實例包括:

  • 一些低級別opperands被鍵入諸如「添加兩個int」,其中作爲CLR使用一個多態操作數。 (即fadd/iadd/ladd vs只是添加)
  • 目前,JVM執行更多攻擊性運行時分析和優化(即熱點)。 CLR目前進行JIT優化,但不是運行時優化(即在運行時替換代碼)。
  • CLR不內聯虛擬方法,JVM不支持...
  • 支持CLR中的值類型,而不僅僅是「基元」。