基本概念:
1、.net 架構的組成
(1)CLR(Common Language Runtime) 公共語言運行時,提供內存管理,代碼安全性檢查等功能。
(2)FCL(.NET Framework Class Library) .net 框架類庫,提供大量應用類庫。
2、CLR的結構
(1).CLS 公共語言規范,獲取各種語言轉換成統一的語法規則,是 .net 跨語言開發的基礎
(2)CTS 通用類型系統,將各種語言中的數據類型轉換成統一的類型。
(3)JIT 實時編譯器(即時編譯器)用於將轉換之后的語言編譯為二進制語言,交給CPU 執行
CLR一個很重要的特性就是Type安全。CLR在任何時候都知道某個對象的類型。你可以通過GetType
方法獲得,由於該方法不是虛函數,因此不能被覆蓋,也就是說返回的值是永遠真實的。
運行流程概述:
c# 源程序 ---> 經過 CLS、CTS 第一次編譯 ---> 統一規范語言(中間語言 )MSIL(.exe、dll) ----> JIT第二次編譯 ---> 二進制語言 ---> 運行在CPU中
流程詳解:
一、使用VS 編寫程序代碼 eg: .cs文件
二、把上述文件編譯為 .dll (程序集)文件
.dll文件中也包含我們所說的中間語言(IL)
(1)PE/COFF頭:Windows操作系統能加載並執行 .dll 和 .exe 文件,是因為他能夠理解 PE/COFF格式
.PE/COFF(Micorsoft Windows Protable Executable/Commom Object File Format) 可移植可執行/通用對象文件格式。PE/COFF頭包含了供操作系統查看和利用的信息,eg:文件指針
(2)CLR 頭:程序集中包含的CLR 代碼,並不是計算機可以直接運行的,還需要進行即時編譯,so,需要將編譯環境運行起來,因為,PE/COFF之后就是CLR頭,告訴操作系統這個文件是一個.net 程序集,去唄其他類型的可執行程序
(3)清單:相當於一個目錄,描述程序集本身的信息。eg:程序集表示(版本號,名稱等),資源(Resources),組成文件。
(4)元數據:描述了程序集中所包含的內容,包括:程序集包含的模塊、類型、成員、可見性等。注:元數據不包含類型的實現,在 .Net 中查看元數據的過程就叫做 “反射”。
(5)CIL代碼:元數據中類型的實現。包括方法體,字段等
(6)資源文件:eg:圖片,音頻
三、CLR(公共語言運行庫)中的 JIT(即時編譯器 Just-In-Time)將我們的 IL 代碼編譯為機器代碼
1、公共語言運行庫 (common language runtime,CLR) 是托管代碼執行核心中的引擎。
運行庫為托管代碼提供各種服務,如跨語言集成、代碼訪問安全性、對象生存期管理、調試和分析支持。
它是整個.NET框架的核心,它為.NET應用程序提供了一個托管的代碼執行環境。它實際上是駐留在內存里的一段代理代碼,負責應用程序在整個執行期間的代碼管理工作。
2、JIT的主要功能:
(1)在負責實現類型的程序集的元數據中查找被調用的方法
(2)從程序集中找到該方法的 IL
(3)分配內存塊
(4)將 IL 編譯成本機的 CPU 指令,然后把這些東西丟進步驟三中分配的內存里
(5)CPU執行這些指令
JIT 編譯時會使用即時編譯,對不同架構的機器生成不同的機器碼,大部分的代碼優化也在這里。
JIT只有在運行時才會工作,生成項目(Build)時不會工作。
編譯器在編譯時,會對代碼進行檢查,對於只調用過一次的代碼,不會進行優化,多次使用的才會進行JIT優化
通常,程序有兩種運行方式:預先編譯(AOT)與動態編譯。預先編譯的程序在執行前全部被翻譯為機器碼,而動態編譯則是一句一句,邊運行邊翻譯。即時編譯則混合了這二者,一句句編譯源代碼,但是會將翻譯過的代碼緩存起來以降低性能損耗。
當運行程序時,CLR 先會調用類加載器加載需要的類型,加載完成之后,就創建了類型對象,包括方法
當首次調用該類型的 X 方法。由於其沒有對應的機器碼(除非它預先編譯好了,例如Console 類中的方法),CLR 會在調用時遭遇 jmp 指令(目標為 JIT 編譯器),將 X 方法的 IL 代碼轉換為機器碼。
JIT 編譯過程中,會做運行時的類型驗證,將代碼和元數據中的定義進行比對,確定代碼的類型安全性。
編譯完成之后,將機器碼存儲在緩存中,並將緩存地址放在 jmp 指令的后面,代替之前的 JIT 編譯器地址。
以后對該方法的所有調用都不需要再次 JIT 編譯, JIT 已將將機器碼儲存在內存中。當程序結束后,這些機器碼就會消失,所以每次程序運行都伴隨着即時編譯。
不過,這個現象帶來的性能損耗僅僅會在方法第一次調用時體現,而大部分程序都會調用方法不止一次