共用方式為


將 MSIL 編譯成機器碼

更新:2007 年 11 月

Microsoft Intermediate Language (MSIL) 必須先根據 Common Language Runtime 編譯成機器碼 (該程式碼是根據目標電腦架構的 Common Language Runtime 編譯) 才能執行。.NET Framework 提供兩種執行這項轉換的方式:

使用 Just-In-Time 編譯器編譯

當載入和執行時組件內容時,JIT 編譯會視需要於應用程式執行階段將 MSIL 轉換成機器碼。由於 Common Language Runtime 會為每個支援的 CPU 架構提供 JIT 編譯器,因此開發人員可以建置可在不同架構的電腦上進行 JIT 編譯和執行的 MSIL 組件集。然而,如果您的 Managed 程式碼呼叫特定平台的原生 (Native) API 或特定平台的類別庫,便只能在特定的作業系統中執行。

JIT 編譯會考慮某些程式碼在執行期間可能從不會被呼叫的事實。它並非使用時間和記憶體將可移植執行檔 (PE) 中所有的 MSIL 轉換為記憶體中的機器碼,而是在執行期間依需要轉換 MSIL 並儲存產生的機器碼,以供該處理序內容中的後續呼叫存取。載入和初始化型別時,載入器會建立和附加 Stub 至型別中的每一個方法。初次呼叫方法時,Stub 會將控制項傳遞至 JIT 編譯器,該編譯器會將該方法的 MSIL 轉換成機器碼,並且將 Stub 修改為直接指向產生的機器碼。因此,JIT 編譯方法的後續呼叫會直接進行至機器碼。

使用 NGen.exe 產生安裝階段程式碼

由於 JIT 編譯器會在呼叫該組件中所定義個別方法時,將組件的 MSIL 轉換成機器碼,因此必須包含執行階段的效能影響。在大部分情況下,該校能影響是可接受的。最重要的是,JIT 編譯器產生的程式碼會繫結至觸發編譯的處理序。該程式碼無法跨多個處理序共用。為了允許跨應用程式的多個引動過程,或共用組件集的多個處理序共用產生的程式碼,Common Language Runtime 支援事先編譯模式。這個事先編譯模式會使用原生映像產生器 (Ngen.exe) 將 MSIL 組件轉換成機器碼,與 JIT 編譯器相當類似。不過,Ngen.exe 的作業與 JIT 編譯器的作業有三個不同的地方:

  • 它會事先執行從 MSIL 至機器碼的轉換,而不是在執行應用程式時。

  • 它會一次編譯整個組件,而非一次一個方法。

  • 它會將原生映像快取中產生的程式碼保存為磁碟上的檔案。

程式碼驗證

在將 MSIL 編譯成機器碼的過程中,MSIL 程式碼必須通過驗證程序,除非系統管理員建立的安全性原則允許程式碼略過驗證。驗證會檢查 MSIL 和中繼資料 (Metadata),以找出該程式碼是否為型別安全,這表示它僅存取獲得授權可存取的記憶體位置。型別安全有助於隔離出各物件,因此也就能夠免於無心或蓄意的毀損。它也提供保證,程式碼的安全性限制將會可靠地強制執行。

對執行階段而言,一個可以被確認為型別安全的程式碼會滿足下列條件:

  • 型別的參考與正被參考的型別完全相容

  • 只有適當定義的作業在物件上被叫用

  • 識別是它們所要求的

在驗證處理期間,MSIL 程式碼會受檢查以確認程式碼只會使用有正確定義的型別來存取記憶體位置和呼叫方法。例如,對於一個會存取超出物件欄位記憶體範圍外位址的程式碼是不被允許的。此外,驗證會檢視程式碼,以判斷 MSIL 是否已經正確產生,因為不正確的 MSIL 可能會違反型別安全規則。驗證程序會讓妥善定義的型別安全程式碼集合通過驗證,它也只會讓型別安全的程式碼通過驗證。然而,由於驗證程序的某些限制,某些型別安全程式碼可能無法通過驗證,而某些語言由於設計之故,不會產生可確認的型別安全程式碼。如果安全性原則需要型別安全程式碼,但該程式碼沒有通過驗證,則在程式碼執行時會產生例外狀況。

請參閱

概念

Managed 執行程序