最近被找工作的事情愁白了頭,只希望這次寒冬能夠早點過去;廢話不多說,開始記錄下最近正在學習CLR的一些個人見解

1.什麼是CLR?

CLR(Common Language Runtime)即公共語言運行時,是一個由多種編程語言使用的「運行時」,我的理解是就是運行環境,類似於jvm虛擬機的東西,只不過CLR並不關心你用的語言是什麼,無論你用的是C#,或者C++等,當通過編譯器編譯後,都會轉換為CLR可以識別的中間語言IL

2.CLR的工作方式

CLR是不和模塊工作的,它和程序集工作,如下

當載入了公共語言運行時時,電腦必須安裝了.NET Framework,同時CLR會檢測目標平臺,如32位Windows,或64位windows,然後決定創建對應的進程;

如圖1-2,託管程序集同時包含元數據和IL,當編譯器把源代碼轉換為中間語言IL後,為了執行方法,CLR會把方法的IL轉換為本機(native)CPU指令,即JIT(just in time「即時」)編譯

在方法執行前,CLR會檢測代碼引用的所有類型,然後分配一個內部數據結構來管理引用訪問,在這個數據結構中每個方法會有一個對應的記錄項,每個記錄項都包含地址,根據地址找到函數的實現,CLR將每個記錄項都設置成(指向)一個內部的未編檔函數,即JITCompiler當方法首次調用WriteLine時,JITCompiler會被調用,將方法的IL代碼編譯為本機的CPU指令。當方法第一次被調用時,JIT編譯器會驗證IL代碼,當第二次時,由於第一次已經完成了驗證和編譯,所以第二次會直接執行。

關於CLR的部署,打包等我不做贅述,因為,我是做Unity的,所以涉及的比較少,所以我還是記錄下和Unity有關的問題:

1.Mono

mono即基於.NET Framework 的開源實現,基於C#的ECMA標準,包含C#編譯器和CLR。mono使C#擁有了跨平臺的能力。

2.為什麼Mono能跨平臺?

因為它使用了CIL(Common Intermediate Language)的通用中間語言,也叫MSIL的指令集,CIL可以在任何支持CLI(Common Language Infrastructure)「通用語言基礎結構」的環境下運行,由於CIL能運行在所有支持CLI的環境中,比如.net運行時或者mono運行時,也就是說和具體的平臺或者CPU無關。

3.CIL的編譯過程

AOT提前編譯和JIT即時編譯(從代碼本身到CIL,還會編譯成一種位元碼,但我就不贅述了),這也引出了unity熱更新的問題,因為在ios平臺上,mono無法使用JIT引擎,而是以Full AOT的模式運行的(如下圖,不包含ios)

JIT編譯屬於即時編譯,即程序執行時才編譯,解釋一條,執行一條,但也因為這樣有了一些效率上的問題,所以mono會有一部分代碼是AOT進行靜態編譯的,目的就是為了降低JIT編譯的效率問題,但是ios平臺是不允許這種編譯的,所以unity沒有提供熱更新方案,而安卓Dalvik虛擬機用的就是JIT方案,所以沒有這個問題

AOT提前編譯

AOT編譯在程序執行前進行,但是mono的AOT和JIT並不是對立的,AOT同樣也用JIT進行編譯,只不過是程序執行前就已經編譯好了,但是有一部分還會通過JIT進行動態編譯

AOT執行過程:

收集要被編譯的方法-->使用JIT進行編譯-->發射(Emitting)經過JIT編譯的代碼和其他信息-->直接生成文件或者調用本地彙編器進行處理後生成文件。

Full AOT

如上,ios是禁止使用JIT的,但是mono的AOT還是會保留一部分代碼會在運行時編譯,為了破解這個問題,mono提供了Full AOT的模式,即預先對程序集中的所有CIL代碼進行AOT編譯生成映像,然後運行時直接載入這個映像而不在使用JIT。(實際上ios並不是直接把JIT禁止了,而是封了JIT內存的可執行許可權),所以ios也是無法動態載入dll的。

以上僅是個人的一些粗淺理解僅供參考,如發現錯誤歡迎指正!

下一篇將繼續學習CLR一書中的設計類型問題


推薦閱讀:
相關文章