接續上篇,詳細說明 JIT 編譯觸發流程、方法表演變與 Native Image Generator (NGen) 取捨。
JIT 編譯觸發流程
- 類別載入時,方法表 (Method Table/HashTable) 建立,各方法槽指向 PreJitStub(預編譯代理)。
- 首次呼叫方法 (如
A.a1()) 觸發 PreJitStub,呼叫 JIT 內部編譯函數(「JIT 編譯者」)。
- JIT 結合中繼資料與 IL 產生機器碼,存入動態記憶體,修改方法表對應槽位為機器碼入口位址。
- 後續呼叫直接跳轉機器碼,不再經 JIT。

MSCorEE 與 mscorwks 核心職責
- 查找組件類型清單、遍歷方法中繼資料。
- 取得方法 IL、配置記憶體。
- 編譯 IL 為機器碼、修正方法表入口。
- 跳轉執行機器碼。
WinDbg + SOS 實測驗證
- 附加進程、載入
SOS.dll。
!name2ee *!JITTester.A 查看類型資訊。
- 按鈕觸發
new A().a1() 前:方法表顯示 <not loaded yet>(未 JIT)。
- 觸發後重新查看:方法表更新為實際記憶體位址,Stub 被跳轉指令取代。
- 未呼叫的類別 (B) 仍顯示未載入;因建構 A 時實例化 C,故 C 已 JIT。

NGen.exe:慎用
NGen 產生完整原生映像安裝至 GAC,啟動時載入整個映像而非按需 JIT。缺點:
- Framework/CPU/OS 變更即失效回退 JIT。
- 仍需發布 IL 與中繼資料。
- 忽略局部性原理,整體載入佔記憶體,可能需重定位。
- 無法運行時優化、無法跨 AppDomain 共用組件。
- JIT 具備程式碼換出、記憶體壓力平衡能力,嵌入式裝置尤重要。
除非確定啟動效能瓶頸在首次 JIT,否則優先信任 JIT。