在MSIL執行前,必須通過.NET框架的JIT編譯器編譯成本地代碼, 這個本地代碼是基于特定CPU的,而且必須和JIT運行在同一套計算機 體系結構上。由于運行時對于其運行的每一個CPU架構都提供了一個 JIT編譯器,開發人員可以編寫一套可以通過JIT編譯從而運行在不同 架構的計算機上的MSIL代碼(如果你的受控代碼調用了特定平臺的 API或者類庫,那么你的代碼就只能在特定的計算機上執行了)。 JIT編譯的一個想法是基于認識到一些代碼可能在執行過程中從 來都沒有被調用過這樣一個事實,因而與其花費時間和內存將PE文件 中的MSIL全部轉換為本地代碼,不如在執行過程中根據需要編譯,對 于已經編譯好的則存放起來,以供下次調用(這樣就不需要重復編譯 了)。當類型加載的時候,加載器為類型的每一個方法都創建一個存 根,并連接到其上。在最初的調用中,存根把控制權轉到JIT編譯器 ,由JIT編譯器將這個方法的MSIL代碼轉換為本地代碼,并且將存根 指向本地代碼的直接執行地址。對于已經經過JIT編譯的方法,其后 續調用將直接調用已經產生的本地代碼,從而減少了JIT編譯和代碼 執行的時間。 作為編譯MSIL代碼到本地代碼過程的一部分,代碼必須經過一個 驗證階段(除非管理員設置了安全規則,允許代碼不需要驗證)。驗 證將檢查MSIL和元數據以確認代碼是否類型安全的,也就是說這段代 碼是否只訪問其有權訪問的存儲區域。類型安全可以確保對象之間是 安全隔離的,從而避免無意的或者惡意的破壞,同時它也保證了代碼 之上的安全規則是能夠可靠執行的。 運行時可以依靠以下幾個狀態為真來驗證代碼的類型安全: 一個類型的引用對于被引用的類型來說是直接兼容的 在一個對象上,只有適當定義的操作才能夠被調用 標志符和它們所聲明的一致 在驗證階段,MSIL將被檢查已確認代碼只能通過適當定義的類型 去訪問內存和調用方法。比如說,在內存定位允許越界的情況下,代 碼將不允許對象的字段能夠被訪問。另外,驗證也將檢查代碼已確認 MSIL是否是正確的產生的,因為不正確的MSIL代碼會導致對類型安全 規則的違反。驗證階段將通過一套良好定義的類型安全代碼,而且也 只有類型安全的代碼才能夠得以通過。另外,要說明的是,由于驗證 階段的限制,可能會導致一些類型安全的代碼無法通過驗證,同時一 些語言也可能不會產生
|