<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [你必須知道的.NET]第二十六回:認識元數據和IL(下)

      《你必須知道的.NET》網站 | Anytao技術博客 

      [你必須知道的.NET]第二十六回:認識元數據和IL(下)

      發布日期:2009.03.04 作者:Anytao
      ? 2009 Anytao.com ,Anytao原創作品,轉貼請注明作者和出處。

      說在,開篇之前
      書接上回:
      第二十四回:認識元數據和IL(上)第二十五回:認識元數據和IL(中)

      我們繼續。

      終于到了,說說元數據和IL在JIT編譯時的角色了,雖然兩個回合的鋪墊未免鋪張,但是卻絲毫不為過,因為只有充分的認知才有足夠的體會,技術也是如此。那么,我們就開始沿著方法調用的軌跡,追隨元數據和IL在那個神秘瞬間所貢獻的力量吧。 

                                                                                            www.anytao.com
       

      5 元數據和IL在JIT編譯時

      CLR最終執行的只有本地機器碼,所以JIT編譯的作用是在運行時將IL代碼解析為機器碼執行。對于JIT編譯,我們會以專門的篇幅來全面了解,本文只將目光關注于元數據和IL在程序執行時的作用和參與細節。首先,IL是基于棧執行的,執行方法調用時,方法參數、局部變量還有返回值等被分配于棧上,并執行其調用過程,既然是關注JIT編譯時,因此我們自然而然將關注方法的執行,因為JIT編譯是以執行方法調用而觸發的。

      首先,對本文開始的代碼加點新料:

      // Release : code04, 2009/02/24                    
      // Author  : Anytao, http://www.anytao.com
      // List    : Base.cs
      public class Base
      {
          public void M()
          {
              Console.WriteLine("M in Base");
          }
      
          public virtual void N()
          {
              Console.WriteLine("N in Base");
          }
      }

      還有:

      // Release : code05, 2009/02/24                    
      // Author  : Anytao, http://www.anytao.com
      // List    : Three.cs
      public class Three : Base
      {
          private static int ID { get; set; }
      
          public override void N()
          {
              //Something new in Three
              Console.WriteLine("N in Three");
          }
      
          public void M()
          {
              Console.WriteLine("M in Three");
      
              M1();
          }
      
          public void M1()
          {
              Console.WriteLine("M1 in Three");
          }
      }

      還有執行代碼:

      static void Main(string[] args)
      {
          Base three = new Three();
          three.M();
          three.N();
      }

      小窺方法表

      以該例而言,執行Main方法調用時,同時伴隨著對于Three實例的創建,和相應類型信息的加載。我們先將類型信息創建的秘密放在以后的內容中,好留點懸念在未來發揮,哈哈。然而,類型加載一定是在實例創建之前完成的,也就是我們常常提起的方法表創建。類型加載是由class loader負責執行的,其過程簡言之就是從元數據表中獲取相應的類型信息,創建方法表(包含CORINFO_CLASS_STRUCT結構),其結構主要包括非虛方法表和虛方法表,按照繼承的虛方法、新引入的虛方法、實例方法和靜態方法的順序排列,以類Three類型為例其CORINFO_CLASS_STRUCT結構可以表示為:

      Note: 在本例中Three沒有定義任何靜態方法,其方法表中父類方法N已有子類覆寫,同時因為有靜態成員存在的原因,CLR會自動創建類型構造器,詳細情況可參考《你必須知道的.NET》1.2節 “什么是繼承”。

      我們可以同過加載SOS調試來了解相應的方法表信息:

      • 在three.N()調用處打好斷點,來查看該時刻的dump信息,就像一個內存快照,發現多少東西就看攝影師的水準。
      • 然后,通過dumpheap加載類型信息,獲取方法表地址(0x002a354c),
      !dumpheap -type Three
      Address       MT     Size
      01d332c4 002a354c       12     
      total 1 objects
      Statistics:
            MT    Count    TotalSize Class Name
      002a354c        1           12 Anytao.Insidenet.MetadataIL.Three
      • 并根據MT地址,以dumpmt查看相關的MethodDesc信息,
      !dumpmt -md 002a354c
      EEClass: 002a15b4
      Module: 002a2f2c
      Name: Anytao.Insidenet.MetadataIL.Three
      mdToken: 02000003  (E:\anytao\Today\OnWriting\MetadataIL\Anytao.Insidenet.MetadataIL\Anytao.Insidenet.MetadataIL\bin\Debug\Anytao.Insidenet.MetadataIL.exe)
      BaseSize: 0xc
      ComponentSize: 0x0
      Number of IFaces in IFaceMap: 0
      Slots in VTable: 10
      --------------------------------------
      MethodDesc Table
         Entry MethodDesc      JIT Name
      6f756a70   6f5d1328   PreJIT System.Object.ToString()
      6f756a90   6f5d1330   PreJIT System.Object.Equals(System.Object)
      6f756b00   6f5d1360   PreJIT System.Object.GetHashCode()
      6f7c7460   6f5d1384   PreJIT System.Object.Finalize()
      002ac0b8   002a3514     NONE Anytao.Insidenet.MetadataIL.Three.N()
      002ac0d0   002a3540      JIT Anytao.Insidenet.MetadataIL.Three..ctor()
      002ac0a8   002a34f4     NONE Anytao.Insidenet.MetadataIL.Three.get_ID()
      002ac0b0   002a3504     NONE Anytao.Insidenet.MetadataIL.Three.set_ID(Int32)
      002ac0c0   002a3520     NONE Anytao.Insidenet.MetadataIL.Three.M()
      002ac0c8   002a3530     NONE Anytao.Insidenet.MetadataIL.Three.M1()

      經過簡單的Dump,方法表的信息和我們圖示的信息相差無幾,細心的觀眾可能會發現Dump信息中并不包含Three::cctor(),那么你答對了。圖示的cctor是我基于為Three實現了類型構造器(靜態構造函數)而特別加入的,而代碼中dump的方法表并沒有把類型構造器包含在內,這是個小粗心,希望細心的您看得夠透。

      執行細則

      具體的執行過程為為:

      • class loader從TypeDef元數據表加載相關元數據信息,包括當前類型,繼承層次的所有父類和實現的接口元數據,根據這些信息建立CORINFO_CLASS_STRUCT結構:

       

      當然,對class loader,我們可以進行一點知識救急:

       

      上課啦:class loader

      Classic Loader是CLR提供的基本組件之一,作用正像其名稱所宣揚的那樣,load一個Class給CLR,class loader將Metadata和IL從PE文件中取出,并加載到運行時內存,簡單的說就是我們下面要介紹的全過程縮影。

      當然,如果你總是對CLR的Classic Loader耿耿于懷,不能釋然。那么,我們也可以參考MSDN的資料來實現自定義的Classic Loader[How to: Write a Class Loader],希望其中能提供靈光一現的思考。

                                                                                            www.anytao.com

       
      • 加載之后,方法執行之前的CORINFO_CLASS_STRUCT中所有的方法表槽都保存了方法應該執行的行為邏輯,這些信息保存在被稱為方法描述(MethodsDesc)的結構中,而MethodDesc則被初始化為指向IL代碼,同時還包含一個指向觸發JIT編譯的PreJitStub地址,如下:

      上述所有方法描述都指向各自的IL代碼地址和JIT編譯器,在此我們僅僅以N()方法為例來進行說明,詳細的情況可以參考MSDN相關內容。

      • 簡單的說,任何方法第一次執行時都會首先觸發執行JIT編譯,JIT的主要工作就是將IL代碼翻譯為Native Code,并插入指向Native Code的jmp指令地址覆蓋原來的Call JIT Compiler指令:

      • 當該方法再次被執行時,因為MethodDesc中保存了機器碼地址,以后的執行將不會執行JIT編譯過程而直接執行x86(X64)機器碼,實現整個執行過程。

      縱觀整個JIT編譯的全過程,其細節的實現遠比我們這里呈現的復雜,在粗略的步驟中我們大致了解了元數據和IL在整個過程中的作用、角色和關系,對了解CLR運行機制而言,適當的選擇是明智的,如果有更多的心思探索,那么就在以后的歲月中由簡及繁吧,但是相信這一定是一次美妙的旅程。

      6 結論

      Metadata描述了靜態的結構,而IL闡釋了動態的執行,這一靜一動承載了太多的技術奧秘。

      當這篇文章行將結束的時候,我發現牽一發而動全身,由此引入的新問題接踵而至,方法調用、程序集、程序域、CLR加載過程在元數據和IL的分析中若隱若現,也驅使我投入注意在后面的《你必須知道的.NET》中,將這些內容一一過招。由此才能在復雜的概念和本質之余,由點及面的對所有內容綜合把握,形成全面的了解和一條線貫穿的認識,那么未來Anytao將要繼續分享還有:

      系列預告
      • 程序集和模塊
      • 程序域
      • CLR加載過程
      • JIT編譯
      • 方法調用
      • 反射種種
      • 其他…

                                                                                            www.anytao.com

      限于繁忙的原因,我無法給出一個清晰的時間表,但力圖每次的內容都給您出足夠的收獲,如果你對.NET始終心懷興致,那么敬請期待《你必須知道的.NET》更多精彩。 

      anytao | ? 2009 Anytao.com

      2009/03/04 | http://anytao.cnblogs.com/ | http://www.rzrgm.cn/anytao/archive/2009/03/04/must_net_26.html

      本文以“現狀”提供且沒有任何擔保,同時也沒有授予任何權利。 | This posting is provided "AS IS" with no warranties, and confers no rights.

      本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

       

      參考文獻

      溫故知新

      [開篇有益]
      [第一回:恩怨情仇:is和as]
      [第二回:對抽象編程:接口和抽象類]
      [第三回:歷史糾葛:特性和屬性]
      [第四回:后來居上:class和struct]
      [第五回:深入淺出關鍵字---把new說透]
      [第六回:深入淺出關鍵字---base和this]
      [第七回:品味類型---從通用類型系統開始]
      [第八回:品味類型---值類型與引用類型(上)-內存有理]
      [第九回:品味類型---值類型與引用類型(中)-規則無邊]
      [第十回:品味類型---值類型與引用類型(下)-應用征途]
      [第十一回:參數之惑---傳遞的藝術(上)]
      [第十二回:參數之惑---傳遞的藝術(下)]
      [第十三回:從Hello, world開始認識IL]
      [第十四回:認識IL代碼---從開始到現在]
      [第十五回:繼承本質論]
      [第十六回:深入淺出關鍵字---using全接觸]
      [第十七回:貌合神離:覆寫和重載]
      [第十八回:對象創建始末(上)]
      [第十九回:對象創建始末(下)]
      [第二十回:學習方法論]
      [第二十一回:認識全面的null]
      [第二十二回:字符串駐留(上)---帶著問題思考]
      [第二十三回:品味細節,深入.NET的類型構造器]
      [第二十四回:認識元數據和IL(上)]
      [第二十五回:認識元數據和IL(中)]

      posted @ 2009-03-04 00:45  Anytao  閱讀(6146)  評論(30)    收藏  舉報
      主站蜘蛛池模板: 亚洲乱妇熟女爽到高潮的片| 男人的天堂av社区在线| 亚洲中文字幕在线精品一区| 国产欧美日韩精品丝袜高跟鞋| 白白发布视频一区二区视频| 91精品国产蜜臀在线观看| 亚洲成av一区二区三区| 人妻少妇偷人一区二区| 久久美女夜夜骚骚免费视频| 中文字幕理伦午夜福利片| 免费网站看sm调教视频| 国产精品人成视频免费国产| 成人av一区二区亚洲精| 丝袜人妻一区二区三区网站| 亚洲人成网网址在线看| 老司机精品影院一区二区三区| 高清有码国产一区二区| 国产乱子伦精品免费女| 日韩精品专区在线影院重磅| 日韩精品成人一区二区三| 婷婷六月天在线| 无码伊人66久久大杳蕉网站谷歌| 石原莉奈日韩一区二区三区| 精品人妻伦九区久久aaa片| 日本福利一区二区精品| 日韩有码中文字幕国产| 亚洲另类无码一区二区三区| 横峰县| 日韩人妻精品中文字幕专区| 精品免费看国产一区二区| 无套中出极品少妇白浆| 福利网午夜视频一区二区| 亚洲AV国产福利精品在现观看| 欧美成人免费全部| 欧美亚洲色综久久精品国产| 在线涩涩免费观看国产精品| 日本牲交大片免费观看| 亚洲熟妇丰满多毛xxxx| 精品国产迷系列在线观看| 国产精品天天看天天狠| 国产av综合一区二区三区|