什麼是Managed 程式碼(managed code)?
Managed 程式碼是一microsoft的中繼語言(IL),他主要的作用是在.NET FRAMEWORK的公用語言運行庫(CLR)執行代碼前去編譯原始碼,也就是說Managed 程式碼充當著翻譯的作用,原始碼在運行時分為兩個階段: 1.原始碼編譯為Managed 程式碼,(所以原始碼可以有很多種,如VB,C#,J#) 2.Managed 程式碼編譯為microsoft的平台專用語言。
編譯器把代碼編譯成中繼語言(IL),而不是能直接在你的電腦上啟動並執行機器碼。中繼語言被封裝在一個叫程式集(assembly)的檔案中,程式集中包含 了描述你所建立的類,方法和屬性(例如安全需求)的所有中繼資料。你可以拷貝這個程式集到另一台伺服器上部署它。
Managed 程式碼在公用語言運行庫(CLR)中運行。這個運行庫給你的運行代碼提供各種各樣的服務,通常來說,他會載入和驗證程式集,以此來保證中繼語言的正確 性。當某些方法被調用的時候,運行庫把具體的方法編譯成適合本機電腦啟動並執行機械碼,然後會把編譯好的機械碼緩衝起來,以備下次調用。(這就是即時編譯) 隨著程式集的運行,運行庫會持續地提供各種服務,例如自動記憶體回收、運行庫類型檢查和安全支援等。這些服務協助提供獨立於平台和語言的、統一的Managed 程式碼應 用程式行為。
Visual Basic .NET和C#只能產生Managed 程式碼。如果你用這類語言寫程式,那麼所產生的代碼就是Managed 程式碼。如果你願意,Visual C++ .NET可以產生Managed 程式碼。當你建立一個項目的時候,選擇名字是以.Managed開頭的項目類型。例如.Managed C++ application。
什麼是Unmanaged 程式碼(unmanaged code)?
Unmanaged 程式碼就是在Visual Studio .NET 2002發布之前所建立的代碼。例如Visual Basic 6, Visual C++ 6, 最糟糕的是,連那些依然殘存在你的硬碟中、擁有超過15年歷史的陳舊C編譯器所產生的代碼都是Unmanaged 程式碼。Managed 程式碼直接編譯成目標電腦的機械碼,這些代 碼只能運行在編譯出它們的電腦上,或者是其它相同處理器或者幾乎一樣處理器的電腦上。Unmanaged 程式碼不能享受一些運行庫所提供的服務,例如安全和記憶體管理 等。如果Unmanaged 程式碼需要進行記憶體管理等服務,就必須顯式地叫用作業系統的介面,通常來說,它們會調用Windows SDK所提供的API來實現。就最近的情況來看,非託管程式會通過COM介面來擷取作業系統服務。
跟Visual Studio平台的其他程式設計語言不一樣,Visual C++可以建立非託管程式。當你建立一個項目,並且選擇名字以M FC,ATL或者Win32開頭的項目類型,那麼這個項目所產生的就是非託管程式。
區別:
1、Managed 程式碼是一種中繼語言,運行在CLR上;
Unmanaged 程式碼被編譯為機器碼,運行在機器上。
2、Managed 程式碼獨立於平台和語言,能更好的實現不同語言平台之間的相容;
Unmanaged 程式碼依賴於平台和語言。
3、Managed 程式碼可享受CLR提供的服務(如安全檢測、記憶體回收等),不需要自己完成這些操作;
Unmanaged 程式碼需要自己提供安全檢測、記憶體回收等操作。
Managed 程式碼就意味著管理的資料?答案是否定的。
對於Visual Basic和C#來說,生活是簡單的,因為你沒有其它選擇。當你在那些語言裡面聲明一個類,那麼這個類的執行個體會在託管堆中被建立,垃圾收集器(GC)會幫 我們管理這些對象的回收。但是在Visual C++中,你有另一個選擇。即使你正建立一個託管程式,你可以決定哪些類是託管類型,哪些類是非託管類型的。
這就是非託管類型:
class Foo { private: int x; public: Foo(): x(0){} Foo(int xx): x(xx) {} };
這就是託管類型
__gc class Bar { private: int x; public: Bar(): x(0){} Bar(int xx): x(xx) {} };
他們唯一的區別就是類Bar的定義中有__gc關鍵字。這個關鍵字會給代碼帶來巨大的區別。
託管類型是可以被記憶體回收行程所回收的。他們必須要用關鍵字new來建立,永遠都不會在棧中出現。所以下面這行代碼是合法的:
Foo f;
但是這一行代碼就是非法的:
Bar b;
如果我在堆中建立一個Foo對象,那麼我必須要負責清理這個對象:
Foo* pf = new Foo(2); // . . . delete pf;
C++編譯器實際上會用兩個堆,一個託管堆和一個非託管堆,然後通過對new操作符的重載來實現對建立不同類型類的執行個體,分配不同的記憶體。如果我在堆裡面 建立一個Bar執行個體,那麼我可以忽略它。當沒有其他代碼在使用它的時候,記憶體回收行程會自動清理這個類,釋放其佔用的資源。 對於託管類型會有一些約束:它們不能實現多重繼承,或者繼承於非託管類型;它們不能用friend關鍵字來實現私人訪問,它們不能實現拷貝建構函式。所 以,你有可能不想把你的類聲明為託管類型。但是這並不意味著你不想讓你的代碼成為Managed 程式碼。在Visual C++中,你可以選擇。
Managed 程式碼與Unmanaged 程式碼的效能比較 基本上每個人都知道的是,所有.Net語言都將被編譯成為一個叫做IL彙編的中繼語言。但是電腦是如何執行這個中間代碼的,卻是很多人不知道,甚至理解 錯誤了的。 JIT是.NET程式啟動並執行重要組件之一,全稱是即時編譯器。很多人(絕對不是少數,問了很多c++程式員,10個有9個這種想法)都以為JIT其實就是 跟Java VM差不多的東西,是一個Interpreter,在運行時讀取IL彙編代碼,然後類比成x86代碼(也就是俗稱的虛擬機器)。但是事實上,.NET使用的 是更為進階的技術。 .Net程式被載入入記憶體以後,當某段IL代碼被第一次啟動並執行時候,JIT編譯器就會將這段IL代碼,全部編譯成本地代碼,然後再執行。這也就是為什 麼.NET程式第一次運行都啟動很慢的原因! 隨.NET庫,微軟還附帶了一個工具,可以事先將.NET程式所有的IL代碼都編譯成本地代碼並儲存在緩衝區中,這樣一來,這個程式就跟c++編譯的一模 一樣了,沒有任何區別,運行時也可以脫離JIT了(這裡不要混淆了,這裡不是說可以脫離.NET庫,而是說不需要在進行即時編譯這個過程了)。所以,請不 要將.NET和Java混為一談,兩個的運行效率根本不是一個等級的!
JIT的最佳化指的是可以針對本地CPU,在編譯時間進行最佳化。傳統程式在編譯時間,為了保證相容性,通常使用最通用的指令集(比如古老的386指令集)來編譯。而JIT知道CPU的具體類型,可以充分利用這些附加指令集進行編譯,這樣的效能提升是很可觀的。