国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

詳解CLR中Jit編譯發(fā)生的過程

開發(fā) 后端
這里將介紹CLR中Jit編譯發(fā)生的過程,通過筆者深入的探討,希望能對大家了解Jit的發(fā)生過程是怎么樣的有所了解。
理解在CLR中Jit編譯發(fā)生的過程,了解這個首先要從CLR談起。CLR(公共語言運(yùn)行時,Common Language Runtime)和Java虛擬機(jī)一樣也是一個運(yùn)行時環(huán)境,它負(fù)責(zé)資源管理(內(nèi)存分配和垃圾收集),并保證應(yīng)用和底層操作系統(tǒng)之間必要的分離。

CLR是如何找到托管代碼的入口方法并對其Jit的呢?Jit編譯的發(fā)生過程是怎么樣的呢?Jit編譯器和Metadata表又有什么關(guān)系呢?本文試圖尋找出答案,在此之前,不妨先了解一下CLR Header的大致結(jié)構(gòu)。

以如下代碼為例:

  1. Example  
  2. using System;  
  3.  
  4. namespace CLRTesing  
  5. {  
  6. class Program  
  7. {  
  8. static void Main(string[] args)  
  9. {  
  10. System.Console.WriteLine("Hello World!");  
  11. Console.ReadKey();  
  12.  
  13. new P().Display();  
  14.  
  15.  
  16. }  
  17.  
  18. Program()  
  19. {  
  20. Console.WriteLine("Constructor.");  
  21. Console.ReadKey();  
  22. }  
  23.  
  24. static Program()  
  25. {  
  26. Console.WriteLine("Static constructor.");  
  27. Console.ReadKey();  
  28. }  
  29. }  
  30.  
  31. class P  
  32. {  
  33. public void Display()  
  34. {  
  35. System.Console.WriteLine("P!");  
  36. Console.ReadKey();  
  37.  
  38. new Q().Display();  
  39. Console.ReadKey();  
  40. }  
  41. }  
  42.  
  43. class Q  
  44. {  
  45. public void Display()  
  46. {  
  47. System.Console.WriteLine("Q!");  
  48. Console.ReadKey();  
  49. }  
  50. }  

編譯后通過dumpbin工具的到其CLR Header,如圖所示:

dumpbin工具

從圖中可以看到,CLR Header由以下幾個部分組成:

1、CB:表示CLR Header的大小,單位是byte;

2、Run time version:運(yùn)行時版本,包含兩部分MajorRuntimeVersion和MinorRuntimeVersion;

3、Metadata Directory:指出Metadata table的RVA和其大小;

4、Flag:這個標(biāo)識主要是供加載器使用,flag值為0x00000001表示當(dāng)前runtime image僅由IL代碼組成并且對CPU沒有特殊要求;值為0x00000002表示image只能被加載到32位機(jī)中,值為0x00010000表示運(yùn)行時和jit編譯器需要追蹤方法的調(diào)試信息;

5、EntryPointToken:Metadata 表中標(biāo)記為EntryPoint的方法的MethodDef;

6、Resources Directory:CLR的資源,也就是托管資源的RVA和大小,注意與PE文件中存儲Win32資源的section不同;

7、StrongNameSignature Directory:PE文件中供CLR加載器使用的哈希值所處RVA和大小;

8、CodeManagerTable Directory:Code Manager 表的RVA和其大小;

9、VTableFixups Directory:由非托管C++類型中虛方法的指針組成的數(shù)組;

10、ExportAddressTableJumps Directory:跳轉(zhuǎn)地址表的RVA和大小;

11、ManagedNativeHeader Directory:一般情況下為0。

以上結(jié)構(gòu)可以從CorHdr.h文件中看出,如果裝的是Visual Studio 2005,這個文件在\Microsoft Visual Studio 8\SDK\v2.0\include\。

查看托管PE文件的工具有很多,不用很復(fù)雜的,就園子里的大牛Anders Liu寫的CliPeViwer就很好用,用Reflector可以偷窺其代碼哦。

那么在上面這個結(jié)構(gòu)中我最關(guān)心的是Metadata directory和EntryPointToken,Metadata directory存提供了原數(shù)據(jù)所在內(nèi)存地址的范圍,EntryPointToken告訴我們在原數(shù)據(jù)表中哪個token標(biāo)識的方法是入口方法,這里一定是方法,所以這個token是以6開頭的一個數(shù)。

回到主題,我們從CLR已經(jīng)被載入內(nèi)存、mscorwks.dll中的_CorExeMain2方法接管主線程開始說起:

1、_CorExeMain2方法會調(diào)用System Domain中的SystemDomain::ExecuteMainMethod方法,然后由此方法再去調(diào)用其它方法(具體什么方法參見深入了解CLR的加載過程一文中的第8步), 通過MetaData表提供的接口查找包含.entrypoint的類型,接著返回入口方法(在C#中這個入口方法一定是Main方法)的一個MethodDesc類型的實例;獲取MethodDesc類型實例的這個過程我認(rèn)為是:CLR通過讀取MetaData表,定位入口方法所屬的類型,將包含該類型的Module載入,然后建立這個類型的EECLASS(EECLASS結(jié)構(gòu)中包含重要信息有:指向當(dāng)前類型父類的指針、指向方法表的指針、實例字段和靜態(tài)字段等)和這個類型所包含方法的Method Table(方法表由一個個Method Descripter組成,具體到內(nèi)存中就是指向若干MethodDesc類型實例的地址),通過EEClass::FindMethod方法找到并返回入口方法的MethodDesc類型實例。

MethodDesc這個類型很有意思,它有兩個重要的部分,一個部分叫做m_CodeOrIL,用來存儲編譯好的MSIL在內(nèi)存中的地址,初值為ffffffffffffffff,另一個部分叫做Stub,如果當(dāng)前代碼沒有被編譯為本地CPU指令,那么通過這個Stub會觸發(fā)對Jit編譯器的調(diào)用。

執(zhí)行上述代碼,

[[5737]]

用Windbg 查看,如下:

  1. Windbg1  
  2. 0:000> !name2ee *!CLRTesing.Program  
  3. Module: 790c2000 (mscorlib.dll)  
  4. --------------------------------------  
  5. Module: 00a72c3c (Hello.exe)  
  6. Token: 0x02000002  
  7. MethodTable: 00a73048  
  8. EEClass: 00a7129c  
  9. Name: CLRTesing.Program  
  10.  
  11. 0:000> !name2ee *!CLRTesing.P  
  12. Module: 790c2000 (mscorlib.dll)  
  13. --------------------------------------  
  14. Module: 00a72c3c (Hello.exe)  
  15. Token: 0x02000003  
  16. MethodTable:   
  17. EEClass:   
  18. Name: CLRTesing.P  
  19.  
  20. 0:000> !dumpmt -md 00a73048  
  21. EEClass: 00a7129c  
  22. Module: 00a72c3c  
  23. Name: CLRTesing.Program  
  24. mdToken: 02000002(D:\test\Hello\bin\Debug\Hello.exe)  
  25. BaseSize: 0xc  
  26. ComponentSize: 0x0  
  27. Number of IFaces in IFaceMap: 0  
  28. Slots in VTable: 7  
  29. --------------------------------------  
  30. MethodDesc Table  
  31.  Entry MethodDescJIT Name  
  32. 79371278 7914b928 PreJIT System.Object.ToString()  
  33. 7936b3b0 7914b930 PreJIT System.Object.Equals(System.Object)  
  34. 7936b3d0 7914b948 PreJIT System.Object.GetHashCode()  
  35. 793624d0 7914b950 PreJIT System.Object.Finalize()  
  36. 00a7c011 00a73030 NONE CLRTesing.Program.Main(System.String[])  
  37. 00a7c015 00a73038 NONE CLRTesing.Program..ctor()  
  38. 00da0070 00a73040JIT CLRTesing.Program..cctor() 

CLRTesing.Program類型的靜態(tài)構(gòu)造函數(shù)執(zhí)行時,入口方法Main和CLRTesing.Program的實例構(gòu)造函數(shù)還沒有被Jit,Main方法中引用到的CLRTesing.P類型也沒有被加載,所以它的Method Table和EEClass結(jié)構(gòu)也沒有建立起來。

#p#

2、在Windbg中detach debuggee,隨便敲一個字符讓程序繼續(xù)運(yùn)行;接著,入口方法Main開始執(zhí)行,

入口方法Main開始執(zhí)行

因為Main方法第一次執(zhí)行,所以通過Stub,Jit編譯器會被喚起,由于Main方法引用了CLRTesing.P類型,那么在執(zhí)行前會將CLRTesing.P類型載入,并建立Method Table和其EEClass結(jié)構(gòu),當(dāng)然這個建立過程也要去查找MetaData表,我認(rèn)為這個過程是這樣的:

Main方法被調(diào)用,由于它沒有被Jit過,CLR會通過Main方法的MethodDesc結(jié)構(gòu)的Stub對Jit編譯器進(jìn)行調(diào)用,CLR通過MetaData表的接口找到Main方法對應(yīng)的Token,如下:

Jit編譯

我們可以看到Main方法的RVA是0x00002050,于是去PE文件的.Text section中的Raw Data中查找image base+RVA這個位置處的IL代碼,接著Jit編譯器會對這段IL代碼進(jìn)行驗證,驗證過程通過調(diào)用CheckIL方法來實現(xiàn),這個方法的簽名可以是這樣的:

  1. CHECK CheckIL(RVA il);  
  2. CHECK CheckIL(RVA il, COUNT_T size); 

驗證結(jié)束后把這段IL代碼編譯成本地CPU指令,將編譯后后的CPU指令存到內(nèi)存并修改Main方法的MethodDesc結(jié)構(gòu)中m_CodeOrIL和Stub的值,讓它們指向這個新的內(nèi)存地址,當(dāng)這個方法被再次調(diào)用的時候就會直接通過這個地址訪問到本地CPU指令而不會觸發(fā)第二次編譯。對于這個過程大家的看法呢?用Windbg查看各對象情況:

  1. Windbg2  
  2. 0:000> !name2ee *!CLRTesing.Program  
  3. Module: 790c2000 (mscorlib.dll)  
  4. --------------------------------------  
  5. Module: 00a72c3c (Hello.exe)  
  6. Token: 0x02000002  
  7. MethodTable: 00a73048  
  8. EEClass: 00a7129c  
  9. Name: CLRTesing.Program  
  10.  
  11. 0:000> !name2ee *!CLRTesing.P  
  12. Module: 790c2000 (mscorlib.dll)  
  13. --------------------------------------  
  14. Module: 00a72c3c (Hello.exe)  
  15. Token: 0x02000003  
  16. MethodTable: 00a730b8  
  17. EEClass: 00a71730  
  18. Name: CLRTesing.P  
  19.  
  20. 0:000> !name2ee *!CLRTesing.Q  
  21. Module: 790c2000 (mscorlib.dll)  
  22. --------------------------------------  
  23. Module: 00a72c3c (Hello.exe)  
  24. Token: 0x02000004  
  25. MethodTable:   
  26. EEClass:   
  27. Name: CLRTesing.Q  
  28.  
  29. 0:000> !dumpmt -md 00a73048  
  30. EEClass: 00a7129c  
  31. Module: 00a72c3c  
  32. Name: CLRTesing.Program  
  33. mdToken: 02000002(D:\test\Hello\bin\Debug\Hello.exe)  
  34. BaseSize: 0xc  
  35. ComponentSize: 0x0  
  36. Number of IFaces in IFaceMap: 0  
  37. Slots in VTable: 7  
  38. --------------------------------------  
  39. MethodDesc Table  
  40.  Entry MethodDescJIT Name  
  41. 79371278 7914b928 PreJIT System.Object.ToString()  
  42. 7936b3b0 7914b930 PreJIT System.Object.Equals(System.Object)  
  43. 7936b3d0 7914b948 PreJIT System.Object.GetHashCode()  
  44. 793624d0 7914b950 PreJIT System.Object.Finalize()  
  45. 00da00b0 00a73030JIT CLRTesing.Program.Main(System.String[])  
  46. 00a7c015 00a73038 NONE CLRTesing.Program..ctor()  
  47. 00da0070 00a73040JIT CLRTesing.Program..cctor()  
  48.  
  49. 0:000> !dumpmt -md 00a730b8  
  50. EEClass: 00a71730  
  51. Module: 00a72c3c  
  52. Name: CLRTesing.P  
  53. mdToken: 02000003(D:\test\Hello\bin\Debug\Hello.exe)  
  54. BaseSize: 0xc  
  55. ComponentSize: 0x0  
  56. Number of IFaces in IFaceMap: 0  
  57. Slots in VTable: 6  
  58. --------------------------------------  
  59. MethodDesc Table  
  60.  Entry MethodDescJIT Name  
  61. 79371278 7914b928 PreJIT System.Object.ToString()  
  62. 7936b3b0 7914b930 PreJIT System.Object.Equals(System.Object)  
  63. 7936b3d0 7914b948 PreJIT System.Object.GetHashCode()  
  64. 793624d0 7914b950 PreJIT System.Object.Finalize()  
  65. 00a7c04c 00a730a8 NONE CLRTesing.P.Display()  
  66. 00a7c058 00a730b0 NONE CLRTesing.P..ctor() 

我們可以發(fā)現(xiàn)Main方法已經(jīng)被Jit,且它引用的CLRTesing.P類型的相關(guān)結(jié)構(gòu)也已經(jīng)建立起來了,而CLRTesing.P類型的Display方法所引用的CLRTesing.Q類型沒有被載入。

總結(jié)一下,Jit編譯針對的對象總是方法,不論是入口方法還是其他方法的Jit過程都類似上述過程,Metadata這這里的作用不言而喻,可以說沒有Metadata的支持就無法進(jìn)行Jit,我覺得Meatadata在Jit編譯期間的作用至少有三個:

1、Jit編譯器通過查找Metadata來找到入口方法;

2、Jit編譯器通過查找Metadata來定位待編譯方法并利用其RVA找到存儲于PE文件中的IL代碼在內(nèi)存中的實際地址;

3、Jit編譯器在找到IL代碼并準(zhǔn)備編譯為本地CPU指令前所進(jìn)行的IL代碼驗證同樣會用到Metadata,例如,驗證方法的合法性需要去核實方法參數(shù)數(shù)量是正確的、傳給方法的每個參數(shù)是否都有正確的類型、方法返回值是否正確等等。

文中是一些我通過Shared Source Common Language Infrastructure(SSCLI)看到的和感覺到的東西,希望能給大家理解Jit提供一點幫助,如果有錯誤的地方也請大家指出,大家一起學(xué)習(xí)。

最后要說明的是,SSCLI里東西僅作為理解CLR使用,與MS真正實現(xiàn)CLR的過程可能不一樣。最后,大家在看SSCLI的時候可以使用Source Insight,個人感覺還挺好用。

 SSCLI的下載地址是:http://www.microsoft.com/downloads/details.aspx?FamilyId=8C09FD61-3F26-4555-AE17-3121B4F51D4D&displaylang=en。

本文來自Leo Zhang博客園文章《深入了解Jit編譯發(fā)生的過程

【編輯推薦】

  1. C#treeview遞歸操作數(shù)據(jù)庫淺析
  2. C#遞歸樹實現(xiàn)實例簡析
  3. C#打開記事本實現(xiàn)實例解析
  4. C#調(diào)用記事本實例淺析
  5. C#日期格式化方法簡析
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2009-10-23 09:36:25

.Net Compac

2009-08-24 11:36:27

CLR加載過程

2023-10-31 11:46:32

編譯器托管CLR

2022-05-18 07:58:21

Linux程序編譯代碼

2020-11-09 14:41:58

iOS 14.2蘋果JIT

2009-09-18 10:40:05

CLR存儲過程

2024-11-27 16:25:54

JVMJIT編譯機(jī)制

2009-10-22 13:02:47

SQL CLR存儲過程

2009-10-22 18:06:31

CLR存儲過程

2009-09-18 14:09:57

SQL CLR存儲過程

2009-10-22 14:05:55

CLR存儲過程

2009-09-17 19:19:17

CLR存儲過程

2011-08-17 17:29:32

Windows編譯MySQL

2009-10-19 14:25:16

靜態(tài)構(gòu)造函數(shù)

2009-09-18 10:55:17

CLR存儲過程

2009-03-11 10:29:23

代碼契約.NETCLR

2011-05-03 10:31:59

噴墨打印機(jī)注墨誤區(qū)

2009-10-22 15:09:40

CLR存儲過程

2022-04-10 10:57:06

eBPFJIT即時編譯

2009-05-15 09:33:52

開發(fā)線程沖突lock
點贊
收藏

51CTO技術(shù)棧公眾號

国产精品久久久久蜜臀| 日本国产一区二区三区| 91av在线免费观看| 日韩片电影在线免费观看| 337p粉嫩大胆噜噜噜鲁| 久久五月激情| 欧美性视频在线| 成年网站在线视频网站| 国产综合欧美| 成人免费淫片视频软件| 99在线精品视频| 2021av在线| 欧美美女15p| 亚洲图区一区| 欧美精品一区二区三区视频| 第四色日韩影片| 国产精品亲子伦对白| 福利在线观看| 日本中文字幕在线播放| av成人亚洲| 久久中文字幕电影| 91精品久久久久久久久久入口| 亚洲女同一区| 91精品91久久久中77777| 中文字幕一区免费| 亚洲一区二区不卡免费| 国产在线制服美女| 五月婷婷色综合| 国产黄在线观看免费观看不卡| 欧美色图第一页| 欧美片一区二区三区| 一本一道久久a久久| 欧美亚洲伦理www| 久久精品国产大片免费观看| 4hu四虎永久在线影院成人| avtt天堂资源网站| 国产欧美一二三区| 日本在线视频一区| 国产精品视频黄色| 亚洲精品看片| 久久综合给合久久狠狠色| 欧美激情影院| 蜜月aⅴ免费一区二区三区| 福利影院在线看| 成人3d精品动漫精品一二三| 精品免费国产一区二区三区四区| 一区二区三区不卡在线视频| 国产精品一区二区在线播放 | 在线观看国产视频| 激情小说 在线视频| 日韩一级片在线播放| av大片在线| 欧美一区二区三区精品| 国产精品无码久久久久| 国产精品一区二区久久久| 亚洲一区二区三区四区在线播放| 国产亚洲一卡2卡3卡4卡新区| 91精品国产99久久久久久红楼| 首页欧美精品中文字幕| 精品www久久久久奶水| 无码av免费一区二区三区试看| 怡红院在线播放| 色综合天天狠天天透天天伊人| 91精品国产91久久综合| 欧美另类videos| 同产精品九九九| 国产精品日韩一区二区三区| 成人午夜av在线| 色播色播色播色播色播在线| 亚洲欧美中文字幕在线一区| 欧美日韩国产免费观看视频| www.激情网| 欧美性受xxxx黑人xyx性爽| 精品国产黄a∨片高清在线| 亚洲综合一区二区不卡| 94色蜜桃网一区二区三区| 日本免费一区二区三区最新| 在线观看欧美日韩| 亚洲国产免费| 国产偷国产偷亚洲清高网站| 欧美亚洲高清| 国产九九九九九| 欧美日韩中文精品| 国产精品一区二区三区美女| 先锋影音亚洲资源| 亚洲va国产va欧美va观看| 小h片在线观看| 国产传媒一区| 亚洲另类中文字| 色999久久久精品人人澡69| 日本黑人久久| 国语一区二区三区| 午夜精品视频在线观看一区二区| 亚洲一二三区不卡| 91九色成人| 亚洲欧美日韩精品综合在线观看| 性做久久久久久免费观看| 超碰国产精品一区二页| 中文字幕在线亚洲精品| 欧美日韩亚洲综合| 国产高清欧美| 嫩草懂你的影院| 国产一区二区三区视频在线播放| 91九色porny在线| 欧美激情精品久久久久久免费印度 | 九九热在线视频观看这里只有精品| 在线成人福利| 国模视频一区二区| 成人精品视频一区二区三区 | 99热一区二区三区| 6080日韩午夜伦伦午夜伦| 国产91色在线观看| 亚洲精品福利在线观看| 老司机一区二区三区| 高清中文字幕一区二区三区| 国产综合久久久久久| 一区二区三区在线观看网站| 日韩成人久久| 妺妺窝人体色www在线小说| 中文字幕日韩高清| 成人动漫在线一区| 国产成人精品一区二三区在线观看 | 快射av在线播放一区| 成人在线视频福利| 一区二区三区免费在线观看| 成人台湾亚洲精品一区二区| 日本精品www| 久久最新资源网| 成人黄色大片在线观看 | youjizzjizz亚洲| 日本精品一区二区三区四区 | 女人让男人操自己视频在线观看| 欧美国产一区二区在线| 51精品秘密在线观看| 国产一在线精品一区在线观看| 无线免费在线视频| 99理论电影网| 在线91免费看| 蓝色福利精品导航| 网友自拍亚洲| 国产偷人视频免费| 国产一区中文字幕| 婷婷综合六月| 成人免费在线小视频| 色一区av在线| 91日韩精品一区| 国产精品17p| 在线看三级网站视频| 国产精品久久精品视| 欧美电影精品一区二区| 国产曰批免费观看久久久| 亚洲一区av| 宅男午夜在线| 黑人巨大精品欧美一区二区小视频| 日韩精品中午字幕| 日本中文字幕电影在线免费观看 | 色婷婷成人在线| 国产成人在线一区二区| 欧美午夜精品久久久久久浪潮| 亚洲久久视频| 日韩高清中文字幕一区二区| 精品久久久噜噜噜噜久久图片| 国产成人拍精品视频午夜网站| 欧美日韩一区二区在线| 久久久久久久高潮| 欧美一级特黄aaaaaa在线看片| 亚洲精品国产精品自产a区红杏吧 亚洲精品国产精品乱码不99按摩 亚洲精品国产精品久久清纯直播 亚洲精品国产精品国自产在线 | 免费av在线| 992tv成人免费观看| 久操成人在线视频| 黑人与娇小精品av专区| 蜜桃精品视频在线| 中文在线综合| 91高清在线| 欧美成人免费在线观看视频| 国产精品美女在线| 亚洲精品第一页| 亚洲精品视频一区| 日韩国产一区二| 亚洲精品合集| 精品51国产黑色丝袜高跟鞋| 午夜视频在线瓜伦| 国产精品嫩草在线观看| 日韩视频中文字幕| 欧洲精品视频在线观看| 白白色 亚洲乱淫| 欧美欧美全黄| 青青伊人久久| 91美女视频在线| 已婚少妇美妙人妻系列| 成人高清在线观看| 一本一道久久a久久精品逆3p| 欧美日韩亚洲精品内裤| gogo大胆日本视频一区| 亚洲黄色成人| 一本色道久久综合亚洲精品酒店 | 国产成人ay| 日本不卡1234视频| 深夜福利视频在线免费观看| 国模吧无码一区二区三区|