術語:CLR :Common Language Runtime 公共語言運行期,有多種不同編程語言使用的運行庫
托管模塊:Managed Module,一個標准的MS Window可移植執行體文件(32位PE32或64位PE32+)
IL:Intermediate Language 中間語言,又叫托管代碼(由CLR管理它的執行)
元數據:metadata,一系列特殊的數據表
程序集:Assembly,抽象的
JIT:just-in-time 即時編譯,將IL編譯成本地CPU指令(本地代碼)
FCL:Framework Class Library,Framework 類庫
CTS:Common Type System,通用類型系統,描述了類型的定義及其行為方式
CLI:Common Language Infrastructure,公共語言基礎結構,這是MS提交給ECMA的一個標准,由CTS 和其他Framwork組件構成
CLS:Common Language Specfication,公共語言規范,詳細規定了一個最小特性集
1.1 將源代碼編譯成托管模塊
CLR編譯過程: C#源碼文件——C#編譯器編譯——托管模塊(IL和元數據)
托管模塊的各個部分:
1.PE32或PE32+頭
標志了文件類型,GUI/CUI/DLL,文件生成時間,在32位還是64位上運行
2.CLR頭
CLR版本,入口方法,模塊元數據,資源,強名稱
3.元數據
3種類型的表
4.IL代碼
元數據包括:
1.描述了模塊中定義的內容,比如類及其成員
2.指出了托管模塊引用的內容,比如導入的類及其成員
3.清單manifest,描述了構成Assembly的文件,由Assembly中的文件實現的公共導出類型,與 Assembly相關聯的資源/數據文件
元數據總是嵌入到與代碼相同的EXE/DLL中,始終與IL保持同步。
元數據用途:
1.消除了對頭/庫文件的依賴,直接從托管模塊中讀取
2.智能感知,從元數據中解析
3.代碼驗證,使用元數據確保代碼只執行安全操作
4.正反序列化
5.垃圾收集器跟蹤對象的生存期以及對象的類型
1.2 將托管模塊合並成程序集
程序集:一個或多個托管模塊/資源文件的邏輯分組,是最小的重用,安全性以及版本控制單元。
既可以生成但文件程序集,也可以生成多文件程序集,這由編譯器工具決定。
CLR是和程序集一起工作的,而不是和托管模塊
1.3 加載CLR
CLRVer命令,查看機器上所有CLR版本
csc的 /plattform開關,決定生成什麼樣的程序集:AnyCPU,x86,x64,Itanium
1.4 執行Assembly代碼
ILAsm命令,將IL編譯成Assembly;ILDasm將Assembly編譯成IL。
高級語言(C#)只是CLR的一個子集,IL則允許訪問CLR的所有功能。
JITCompiler函數,又名JIT編譯器(JITter)
在方法首次執行時,CLR檢測出Main的代碼引用的所有類型,於是CLR分配一個內部數據結構,用於管 理對引用類型的訪問。
在這個內部結構中,每個方法都有一條對應的紀錄以及地址。
對此結構進行初始化時,CLR將每條紀錄都設置為CLR內部包含的一個未文檔化的函數,即 JITCompiler函數。
JITCompiler函數被調用時,找到相應方法的IL,編譯成本地CPU指令,並保存到一個動態內存塊中, 將該內存地址存入內部結構中,最後JITCompiler函數會跳轉到內存塊中的代碼,執行。
第二次執行該方法時,不需要再編譯,直接執行內存塊中的代碼。
JIT將本地代碼保存在動態內存中,一旦程序終止,本地代碼會被丟棄。
csc命令有2個開關會影響代碼的優化:/optimize ,/debug
開關設置 IL代碼質量 JIT本地代碼質量
/optimize- ,/debug- 未優化 優化 默認設置 /optimize- ,/debug(+/full/pdbonly) 未優化 未優化 VS2005 Degug狀態 /optimize+ ,/debug(-/full/pdbonly) 優化 優化 VS2005 Release狀態
生成未優化的IL時,會在IL中生成NOP指令用於調試,設置斷點。
IL是基於堆棧的。所有指令都是:將操作數壓棧,結果則從棧中彈出
IL有安全驗證機制,保證每一行IL代碼是正確的,不會非法訪問內存,每個托管EXE都在獨自的 AppDomain中運行。
不安全代碼:允許C#直接操作內存字節,在COM互操作時使用,csc以/unsafe開關標記包含不安全代碼 ,其中所有方法都使用unsafe關鍵字。
PEVerify命令檢查程序集所有方法,指出其中的不安全代碼方法。
1.5 本地代碼生成器 NGEN.exe
NGEN.exe將IL預先編譯到硬盤文件中,可以加快程序的啟動速度,減小程序的工作集(所有加載該程序 集的AppDomain不再copy其副本,因為該程序集已經與編譯到文件中,是代碼共享的)。
缺點是:
不能保護IL外洩
生成的文件可能失去同步
因為在文件中要計算首選基地址,而NGEN是靜態計算好的,所以要修改基地址,速度會慢下來
較差的執行性能,NGEN生成的代碼沒有JIT好。
如果不能使用NGEN生成的文件,會自動加載JITCompiler。
1.7 CTS
CTS的一些規定:
1.一個類型可以包含0個或多個成員
2.類型可視化以及類型成員的訪問規則
3.定義了繼承,虛方法,對象生成期的管理規則
4.所有類型最終都從預定義的System.Object繼承
1.8 CLS
如果在C#中定義的類型及其方法,可以在VB中使用,那麼,就不能在C#中定義CLS外的任何 public/protected特性,privated的類型及其成員不受限制。
C#可以有僅大小寫不同的兩個方法——不符合CLS,所以不能是public的。
使用[assembly:CLSComplant(true)]標志程序集,告訴編譯器檢查該程序集的CLS相容性。書上寫得不 明白,我這裡做了一個測試:
using System; [assembly: CLSCompliant(true)] namespace ClassLibrary2 { public class Class1 { public void A() { } public void a() { } } }
注意,[assembly:CLSComplant(true)]要寫在namespace外。
我定義了兩個不同方法A和a,編譯器會有警告,說這樣的語法不兼容CLS;如果去掉 [assembly:CLSComplant(true)]聲明,那麼不會有這個警告;如果將a方法改為private,則不會有警告。
中途我使用了ILDasm觀察這個dll,發現兩個方法A和a都存在於IL中,說明IL的語法范圍也大於CLS。
在VB中,我添加了對此dll的引用:
Imports ClassLibrary2 Module Module1Module Module1 Public Class TClass T Public Function A()Function A() As Integer Dim c1 As Class1 = New Class1() End Function End Class End Module
發現,在c1.後面不會有A或a方法的智能感知,說明VB不能識別不符合CLS的語法。如果修改了dll中的 a方法為private或者刪除a方法,則在VB中可以智能感知到A方法。
可以得出結論,不符合CLS的語法,在另一種語言中是看不到的。
1.9 COM互操作
3種互操作情形:
1.托管代碼可以調用DLL中包含的非托管函數,如Kernal32.dll,User32.dll
2.托管代碼可以使用現成的COM組件
3.非托管代碼可以使用托管類型(C#寫的ActiveX控件或shell擴展)