我的家园

我的家园

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

Posted on 2012-04-15 16:27 zljpp 阅读(123) 评论(0)  编辑  收藏

前面两个例子,一个简单的替换了二进制的编码一个通过理解class的文件格式,可以增加输出的内容,都非常简单,但是实际可能用到的不会这么简单,更多的是对方法的操作,比如spring aop的实现方式有两种动态代理和字节码增强,其中字节码增强便可以通过修改class的二进制文件完成,另外对性能分析、调试跟踪和日志记录,也可以通过这种方式简单的实现,当然在现实中我们不会去真正的操作二进制码,我们一般通过第三方的库文件,比如:asm、 cglib、 serp、 和bcel等;但是他们的本质还是去操作二进制码;前面在分析helloworld.class 的时候,还剩下两块内容当时没有讨论(其实是一样的结构),这里我们先讨论这两块内容:

第一块: 第39点后面剩下的29个字节如下(请先回顾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;表示该方法执行的时候操作数栈最大的长度;这里表示操作数栈的长度为1;

(2)、0X 00 01表示 max_locals;表示方法局部变量所需要的空间的长度,

(3)、0X 00 00 00 05 表示code_length=5;即后面的5个字节为code的内容;

(4)、0X 2A B7 00 01 B1 :5个字节表示的便是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; 新行开始时,代码数组的偏移量,该偏移量从代码数组的起始位置开始;

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

 

LineNumberTable  中包含了一些调试信息,不做讨论;
到这里第一块结构就ok了;

 

第二块: 第41点后面剩下的37个字节如下(请先回顾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;表示该方法执行的时候操作数栈最大的长度;这里表示操作数栈的长度为2;

(2)、0X 00 01 表示 max_locals;表示方法局部变量所需要的空间的长度

(3)、0X 00 00 00 09 表示code_length=5;即后面的9个字节为code的内容;

(4)、 B2 00 02 12 03 B6 00 04 B1 :9个字节表示的便是code 的内容;

      该code[] 包含的实现该方法的JVM 的实际的字节,

 

  • 0X B2 :getstatic 指令:表示获取指定类的静态域,并将其值压入栈顶,后面的0X 00 02 ;查看2号常量池,即将out(sysytem.out)压入栈
  • 0X 12 :ldc:表示将一个常量池压入操作栈,后面的0X 03 便是这个操作数,查看第3号常量池,为hello world,我们要输出的内容;
  • 0X B6 : invokevirtual,调用实例方法,后面的0X 00 04 ,查看4号常量池 表示java/io/PrintStream的println方法,这个指令弹出两个操作数,即是调用 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;新行开始时,代码数组的偏移量,该偏移量从代码数组的起始位置开始;

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

 

       3.3)、0X 00 08 表示 start_pc;新行开始时,代码数组的偏移量,该偏移量从代码数组的起始位置开始;

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

LineNumberTable  中包含了一些调试信息,不做讨论;

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

另外:

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

2、对在class 复合数据结构中的 9中属性没有做详细的介绍,只是对用到的code_attribute,sourcefile_attribute,linenumbertable_attribute ,有一个简单的说明,其他还有sythetic、localvariabletable、innerclass、exception、deprecated、constantvalue几种;

 






只有注册用户登录后才能发表评论。


网站导航: