Q1: 什么是CLR?
A1: CLR (Common Language Runtime) 是一個(gè)可以由多種編程語(yǔ)言使用的“運(yùn)行時(shí)”。
Q2: CLR的核心功能有哪些?
A2: 1)內(nèi)存管理;2)程序集加載;3)安全性;4)異常處理;5)線程同步
Q3: CLR與使用的編程語(yǔ)言有關(guān)嗎?
A3: 無(wú)關(guān)。只要編譯器是面向CLR的就行。
Q4: 選用不同編程語(yǔ)言經(jīng)過(guò)面向CLR的編譯器編譯后生成的結(jié)果相同嗎?
A4: 相同。無(wú)論選擇什么語(yǔ)言,相應(yīng)的編譯器變異的結(jié)果都是一個(gè)托管模塊,即一個(gè)標(biāo)準(zhǔn)的32位PE (Portable Executable) 32文件或64位PE32+文件。它們都需要CLR才能執(zhí)行。
Q5: 托管模塊的組成部分是什么,它們的作用分別是什么?
A5: 1)PE32或PE32+頭;2)CLR頭;3)元數(shù)據(jù);4)中間語(yǔ)言
PE32頭:1)標(biāo)識(shí)了文件類型(GUI, CUI, DLL);2)包含一個(gè)文件生成時(shí)間的時(shí)間標(biāo)記;3)包含與本地CPU代碼有關(guān)的信息(在該模塊包含CPU代碼的情況下)。
CLR頭:1)包含需要的CLR版本;2)托管模塊入口方法的MethodDef元數(shù)據(jù)標(biāo)記;3)模塊的元數(shù)據(jù),資源,強(qiáng)名稱,一些標(biāo)記以及不太重要的數(shù)據(jù)項(xiàng)的位置及大小。
元數(shù)據(jù):1)包含描述源代碼中定義的類型及成員的元數(shù)據(jù)表;2)包含描述源代碼中引用的類型和成員。
中間語(yǔ)言:編譯器編譯源代碼生成的代碼,運(yùn)行時(shí)會(huì)被CLR編譯為本地CPU指令。
Q6: 什么是程序集?
A6: 程序集是一個(gè)抽象的概念,它是一個(gè)或多個(gè)模塊/資源文件的邏輯分組,也是重用,安全性以及版本控制的最小單元。 生成的程序集既可以是一個(gè)可執(zhí)行文件(exe)也可以是一個(gè)DLL.
Q7: 托管模塊和程序集之間的關(guān)系是什么?
A7: 默認(rèn)情況下,編譯器實(shí)際會(huì)把生成的托管模塊轉(zhuǎn)換為程序集,程序集的清單中會(huì)指明該程序集僅有一個(gè)文件構(gòu)成。如果項(xiàng)目中只有一個(gè)托管模塊,沒(méi)有資源文件或數(shù)據(jù)文件,那么程序集就是托管模塊。如果想將多個(gè)文件合并到一個(gè)程序集,則需要使用其他工具來(lái)實(shí)現(xiàn)。
Q8: 方法執(zhí)行的過(guò)程是什么?首次執(zhí)行和之后執(zhí)行有區(qū)別嗎?
A8: 執(zhí)行一個(gè)方法需要將程序集中的IL轉(zhuǎn)換為本地CPU指令,這項(xiàng)工作由CLR的JIT(即時(shí))編譯器來(lái)完成。用如下例子講解:
分析準(zhǔn)備階段:
1) CLR檢測(cè)Main代碼引用的所有類型,此例中為Console類型;
2) CLR分配一個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu),用于管理對(duì)引用的類型(即Console類型)的訪問(wèn)。Console類型中的所有方法在這個(gè)內(nèi)部結(jié)構(gòu)中都有一個(gè)入口, 通過(guò)該入口可以找到方法的具體實(shí)現(xiàn);對(duì)該內(nèi)部結(jié)構(gòu)初始化時(shí),CLR將每個(gè)方法的入口都設(shè)置成指向JITCompiler函數(shù)(CLR內(nèi)部未文檔化的一個(gè)函數(shù));
執(zhí)行階段:
1) Main方法中首次調(diào)用WriteLine方法時(shí),JITCompiler函數(shù)會(huì)被調(diào)用,這個(gè)函數(shù)知道調(diào)用的是哪個(gè)方法(WriteLine),以及什么類型(Console)調(diào)用了該方法;
2) JITCompiler在定義了該類型的程序集元數(shù)據(jù)中查找該方法(WriteLine)的IL,并對(duì)IL進(jìn)行驗(yàn)證,若無(wú)誤,則將該IL編譯為本地CPU指令;
3) 將本地CPU指令保存至一個(gè)動(dòng)態(tài)分配的內(nèi)存塊;
4) JITCompiler返回最初為Console類型創(chuàng)建的內(nèi)部結(jié)構(gòu),找到WriteLine方法的入口,并將之前設(shè)置的指向JITCompiler的引用改為指向保存本地CPU指令的內(nèi)存塊;
5) JITCompiler回到保存本地CPU指令的內(nèi)存塊,并執(zhí)行該指令。
當(dāng)Console.WriteLine("Hello")執(zhí)行結(jié)束后,繼續(xù)執(zhí)行下一行代碼Console.WriteLine("Goodbye"),由于Console.WriteLine方法已經(jīng)編譯為本地CPU指令了,就會(huì)跳過(guò)JITCompiler函數(shù)的繁瑣操作,直接執(zhí)行本地CPU代碼。但當(dāng)應(yīng)用程序終止后再次啟動(dòng)運(yùn)行這段代碼,JIT編譯器必須重新將IL編譯為本地CPU指令,因?yàn)橹笆潜4嬖趦?nèi)存塊中的,程序終止后內(nèi)存塊會(huì)被清空。
Q9: IL有什么優(yōu)勢(shì)?
A9: IL可以提高應(yīng)用程序的健壯性和安全性。在將IL編譯為本地CPU指令時(shí),CLR會(huì)執(zhí)行驗(yàn)證過(guò)程,確保代碼做的一切都是安全的(參數(shù)數(shù)量是否正確,參數(shù)類型是否正確,返回值是否被正確使用等等)。
Q10: 比較CLR, CTS和CLS.
A10: CLR是一個(gè)可以由多種編程語(yǔ)言使用的“運(yùn)行時(shí)”, 它是圍繞類型展開(kāi)的,類型為應(yīng)用程序和其他類型公開(kāi)了功能,通過(guò)類型,可以用一種編程語(yǔ)言系的代碼和另一種編程語(yǔ)言寫的代碼進(jìn)行溝通,而CTS則是一個(gè)”通用類型系統(tǒng)”,它描述了類型的定義和行為。而由于CLR允許一種語(yǔ)言使用另一種語(yǔ)言定義的類型,但各種編程語(yǔ)言存在極大的區(qū)別,例如有些語(yǔ)言區(qū)分大小寫而有些語(yǔ)言不區(qū)分,CLS是一個(gè) ”公共語(yǔ)言規(guī)范”, 它定義了一個(gè)最小功能集,用一種語(yǔ)言定義了一種類型時(shí),若想要其他語(yǔ)言可以使用該類型,就不要在該類型的public和protected成員中使用超出CLS的功能。每種編程語(yǔ)言都提供了CLR/CTS的一個(gè)子集以及CLS的一個(gè)超集。
新聞熱點(diǎn)
疑難解答
圖片精選