我的家園

          我的家園

          HelloWorld.class 文件的解讀---方法解讀

          Posted on 2012-04-15 16:27 zljpp 閱讀(132) 評論(0)  編輯  收藏

          前面兩個例子,一個簡單的替換了二進制的編碼一個通過理解class的文件格式,可以增加輸出的內容,都非常簡單,但是實際可能用到的不會這么簡單,更多的是對方法的操作,比如spring aop的實現(xiàn)方式有兩種動態(tài)代理和字節(jié)碼增強,其中字節(jié)碼增強便可以通過修改class的二進制文件完成,另外對性能分析、調試跟蹤和日志記錄,也可以通過這種方式簡單的實現(xiàn),當然在現(xiàn)實中我們不會去真正的操作二進制碼,我們一般通過第三方的庫文件,比如:asm、 cglib、 serp、 和bcel等;但是他們的本質還是去操作二進制碼;前面在分析helloworld.class 的時候,還剩下兩塊內容當時沒有討論(其實是一樣的結構),這里我們先討論這兩塊內容:

          第一塊: 第39點后面剩下的29個字節(jié)如下(請先回顧39點的內容):

          ?

          ?

          0000014fh: 00 01 00 01 00 00 00 05 2A B7 00 01 B1 00 00 00 ; ........*?.?..
          0000015fh: 01 00 0A 00 00 00 06 00 01 00 00 00 01          ; .............

          ?Code_attribute 的定義:

          ?

          ?

          ?

          Code_attribute {          
                  u2 attribute_name_index;  
                   u4 attribute_length;  
                   u2 max_stack;  
                   u2 max_locals;  
                   u4 code_length;  
                   u1 code[code_length];  
                   u2 exception_table_length;  
                   {       u2 start_pc;  
                          u2 end_pc;  
                          u2 handler_pc;  
                          u2 catch_type;  
                   }       exception_table[exception_table_length];  
                   u2 attributes_count;  
                   attribute_info attributes[attributes_count];  
              } 
          ?

          ?

          ?按照Code_attribute 的定義分析29個字符:

          (1)、0X 00 01 表示max_stack;表示該方法執(zhí)行的時候操作數(shù)棧最大的長度;這里表示操作數(shù)棧的長度為1;

          (2)、0X 00 01表示?max_locals;表示方法局部變量所需要的空間的長度,

          (3)、0X 00 00 00 05 表示code_length=5;即后面的5個字節(jié)為code的內容;

          (4)、0X?2A B7 00 01 B1 :5個字節(jié)表示的便是code 的內容;

          ?

          ?

          • 0X 2A :aload_0 表示將第一個引用類型本地變量推送至棧頂 ?
          • 0X B7 :invokespecial???調用超類方法,后面的0X 00 01,查看1號常量池 表示void?init();所有表示調用超類的init方法
          • 0X B1 return 返回void;

          (5)、0X 00 00 :表示exception_table_length=0;也就是說沒有異常處理;

          (6)、0X 00 01 :表示attributes_count=1;接下來有一個attribute_info 的結構:

          ?

          先復習一下attribute_info 的結構定義:

          ?

          ?

          attribute_info {          
           u2 attribute_name_index;  
           u4 attribute_length;  
           u1 info[attribute_length];  
              }

          ?

          ? ? ?1)、0X 00 0A :表示 ?attribute_name_index,查看10號常量池,為LineNumberTable ;查看LineNumberTable ?屬性的定義:

          ?

          ?

          lineNumberTable_attribute{
          U2                         attribute_name_index;
          U4                         attribute_length;
          U2                          line_number_table_length
          line_number_info   line_number_table 
          }
          
          line_number_info  的定義:
          
          line_number_info  {
          U2    start_pc;
          U2    line_number;
          }

          ?

          ? ?2)、0X 00 00 00 06 :表示attribute_length=6,

          ? ?3)、0X 00 01 :表示line_number_table_length=1,即后面有一個line_number_info 結構

          ? ? ? ?3.1)、0X 00 00 表示 start_pc; 新行開始時,代碼數(shù)組的偏移量,該偏移量從代碼數(shù)組的起始位置開始;

          ? ? ? ?3.2)、0X 00 01 表示 line_number=1

          ?

          LineNumberTable ?中包含了一些調試信息,不做討論;
          到這里第一塊結構就ok了;

          ?

          第二塊: 第41點后面剩下的37個字節(jié)如下(請先回顧41點的內容):這個結構和上面的第一塊內容基本一致;

          ?

          0000017ah: 00 02 00 01 00 00 00 09 B2 00 02 12 03 B6 00 04 ; ........?...?.
          0000018ah: B1 00 00 00 01 00 0A 00 00 00 0A 00 02 00 00 00 ; ?..............
          0000019ah: 03 00 08 00 04                                  ; .....
          ?

          ?

          (1)、0X 00 02 表示max_stack;表示該方法執(zhí)行的時候操作數(shù)棧最大的長度;這里表示操作數(shù)棧的長度為2;

          (2)、0X 00 01 表示?max_locals;表示方法局部變量所需要的空間的長度

          (3)、0X 00 00 00 09 表示code_length=5;即后面的9個字節(jié)為code的內容;

          (4)、 B2 00 02 12 03 B6 00 04?B1 :9個字節(jié)表示的便是code 的內容;

          ? ? ? 該code[] 包含的實現(xiàn)該方法的JVM 的實際的字節(jié),

          ?

          • 0X B2 :getstatic 指令:表示獲取指定類的靜態(tài)域,并將其值壓入棧頂,后面的0X 00 02 ;查看2號常量池,即將out(sysytem.out)壓入棧
          • 0X 12 :ldc:表示將一個常量池壓入操作棧,后面的0X 03 便是這個操作數(shù),查看第3號常量池,為hello world,我們要輸出的內容;
          • 0X B6 : invokevirtual,調用實例方法,后面的0X 00 04 ,查看4號常量池 表示java/io/PrintStream的println方法,這個指令彈出兩個操作數(shù),即是調用 out.print("hello world");
          • 0X?B1 : return ;返回void

          ?

          (5)、0X 00 00 :表示exception_table_length=0;也就是說沒有異常處理;

          (6)、0X 00 01 :表示attributes_count=1;接下來有一個attribute_info 的結構:

          ? ?1)、0X 00 0A :表示 ?attribute_name_index,查看10號常量池,為LineNumberTable ;

          ? ? ? ? ? ? ?查 看LineNumberTable ?屬性的定義:

          ?

          ? ?2)、0X 00 00 00 0A :表示attribute_length=10,

          ? ?3)、0X 00 02 :表示line_number_table_length=2,即后面有一個line_number_info 結構

          ? ? ? ?3.1)、0X 00 00 表示 start_pc;新行開始時,代碼數(shù)組的偏移量,該偏移量從代碼數(shù)組的起始位置開始;

          ? ? ? ?3.2)、0X 00 03 表示 line_number=3

          ?

          ? ? ? ?3.3)、0X 00 08 表示 start_pc;新行開始時,代碼數(shù)組的偏移量,該偏移量從代碼數(shù)組的起始位置開始;

          ? ? ? ?3.4)、0X 00 04 表示 line_number=4

          LineNumberTable ?中包含了一些調試信息,不做討論;

          至此 整個helloworld的class 文件全部分析好了,

          另外:

          1、文章中提高的指令集參照?http://thinkinmylife.iteye.com/blog/443900

          2、對在class 復合數(shù)據(jù)結構中的 9中屬性沒有做詳細的介紹,只是對用到的code_attribute,sourcefile_attribute,linenumbertable_attribute ,有一個簡單的說明,其他還有sythetic、localvariabletable、innerclass、exception、deprecated、constantvalue幾種;

          ?






          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 从化市| 云阳县| 陆良县| 易门县| 察隅县| 南安市| 昌宁县| 申扎县| 肇源县| 安溪县| 曲麻莱县| 郓城县| 绵竹市| 清河县| 万荣县| 苏尼特右旗| 沅江市| 康定县| 夹江县| 英山县| 醴陵市| 邹平县| 阜南县| 来凤县| 睢宁县| 辽源市| 浪卡子县| 萍乡市| 威宁| 茌平县| 宜君县| 海城市| 河源市| 清水河县| 泸州市| 九龙城区| 开化县| 凭祥市| 克拉玛依市| 衡阳县| 合江县|