.NET語言的編譯分爲兩個階段.首先高級語言被編譯成一種稱做IL的中間語言,與高級語言相比,IL更像是機器語言,然而,IL卻包含一些抽象概念(好比:類、異常),這也是這種語言被稱爲中間語言的緣由。IL被打包在DLL或EXE文件中,而DLL和EXE在.NET中的主要區別就是:只有EXE能夠直接被運行,而兩者均可被某個正在執行的進程動態裝載(後文詳述)。因爲機器的CPU只能執行本地彙編語言,而不是IL,進一步將IL編譯成彙編語言的工做(也就是第二階段)須要在運行時進行,這個過程由即時編譯器(JIT)完成。
高級語言在初次被編譯時,編譯器作兩件事:首先把編譯獲得的IL存儲在DLL或EXE中,而後爲類的每一個方法建立一個stub函數,此函數會調用即時編譯器,並將自身的地址做爲參數傳給編譯器。即時編譯器則從DLL或EXE中獲取相應的IL,編譯成機器語言,並將內存中的原零時調用函數替換成機器語言。這個過程的思想,是用已編譯的方法調用未編譯的方法,實質上被調用的是stub函數;stub函數再調用編譯器,將自身編譯爲本地機器語言;最後,.NET會從新調用該方法,方法此時才被真正地執行。函數被反覆調用時,機器指令會被直接執行,而只由編譯器對方法進行初次編譯須要花費時間。至於那些沒有被調用的方法,則不會被編譯。
當編譯器生成一個EXE文件後, 該程序的入口函數爲Main() 方法。裝載器將這個EXE 文件載入,探測到該這是一個託管EXE,因而又載入 .NET運行時庫文件(包括即時編譯器), 接着調用了EXE 的Main() 方法。這將觸發對Main()方法的即時編譯, Main()方法在內存中被替換爲本地機器語言,因而 .NET應用程序開始運行。在被編譯爲本地語言後,應用程序即可以自由調用本地代碼了。當程序停止時,本地代碼從內存中釋放,因此在下次運行時,IL須要被即時編譯器從新編譯。函數