(1)access_flags
其中access_flags占两个字节, 描述的是方法的访问标志信息。 这里就不在详细介绍了, 下面给出一张表格(该表格来自《深入Java虚拟机》):| 标志位名称 | 标志值 | 设定含义 | 设定者 |
| ACC_PUBLIC | 0x0001 | 方法设为public | 类和接口 |
| ACC_PRIVATE | 0x0002 | 方法设为private | 类 |
| ACC_PROTECTED | 0x0004 | 方法设为protected | 类 |
| ACC_STATIC | 0x0008 | 方法设为static | 类 |
| ACC_FINAL | 0x0010 | 方法设为final | 类 |
| ACC_SYNCHRONIZED | 0x0020 | 方法设为sychronized | 类 |
| ACC_NATIVE | 0x0100 | 方法设为native | 类 |
| ACC_ABSTRACT | 0x0400 | 方法设为abstract | 类和接口 |
| ACC_STRICT | 0x0800 | 方法设为strictFP | 类和接口的
|
(2)name_index
access_flags下面的两个字节是name_index, 这是一个指向常量池的索引, 它描述的是当前方法的方法名。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的方法名。
(3)descriptor_index
name_index下面的两个字节叫做descriptor_index , 它同样是一个指向常量池的索引, 它描述的是当前方法的描述符。 这个索引指向常量池中的一个CONSTANT_Utf8_info数据项。 这个CONSTANT_Utf8_info数据项中存放的字符串就是当前方法的描述符(关于方法描述符, 在前面的博客中已经有过详细的讲解, 如果不明白, 请参考前面的博客: 深入理解Java Class文件格式(二))。(4)attributes_count和attributes
descriptor_index 下面是attributes_count和attributes 。 这是对当前方法所具有的属性的描述。 这里的属性和源文件中的属性不是同一个概念, 在源文件测层面中, 属性是字段的另一种叫法, 希望读者不要疑惑。读者也不要轻视class文件中的属性, 这些属性可以描述很多的信息。 我们会在后面的文章中进行介绍。attributes_count表示这个字段有几个属性。attributes 可以看成一个数组, 数组中的每一项都是一个attribute_info , 每个attribute_info 表示一个属性, 数组中一共有attributes_count个属性。可以出现在method_info 中的属性有三种, 分别是Code, Deprecated, Exceptions 和Synthetic。 在这几个属性中, 尤其是Code和Exceptions 非常重要, 这两个属性对于在class文件中完整描述一个方法起着至关重要的作用, 其中Code属性中存放方法的字节面指令,Exceptions 属性是对方法声明中抛出的异常的描述 。 这两属性以及其他一些属性, 会在下一篇文章中详细介绍, 敬请关注。
介绍完了每个method_info的结构, 下面我们以代码来说明, 还是使用上面的源码:
package com.jg.zhang;
public class Programer extends Person{
private Computer computer;
public Programer(Computer computer){
this.computer = computer;
}
public void doWork(){
computer.calculate();
}
}
反编译之后, 常量池中会有如下信息(这里省略了大部分无关信息):
Constant pool:
.........
#7 = Utf8
#8 = Utf8 (Lcom/jg/zhang/Computer;)V
.........
#12 = Utf8 ()V
.........
#19 = Utf8 doWork
{
.........
public com.jg.zhang.Programer(com.jg.zhang.Computer);
flags: ACC_PUBLIC
.........
public void doWork();
flags: ACC_PUBLIC
.........
}
由反编译结果可以看出, 该类中定义了两个方法, 其中一个是构造方法, 一个是doWork方法, 且这两个方法都是public的。 这两个方法的描述信息都存放在常量池。 其中第7项的CONSTANT_Utf8_info为构造方法的方法名, 第8项的CONSTANT_Utf8_info为构造方法的方法描述符, 第19项的CONSTANT_Utf8_info为doWork方法的方法名, 第12项的CONSTANT_Utf8_info为doWork方法的方法描述符。
根据常量池中的信息, 可以得出如下的示意图, 该示意图形象的说明了class文件中的method_info是如何引用常量池中的数据项来描述当前类中定义的方法的。 图中虚线范围内表示常量池所在的区域:
< http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPGgxPtfcveE8L2gxPgo8YnI+Cgq1vbTLzqrWuaOsIM7Sw8e+zb3pydzN6sHLY2xhc3POxLz+1tC1xGZpZWxkc7rNbWV0aG9kc6OsIL340NDSu8/C19y94aGjIAo8YnI+CgogZmllbGRzyse21LWxx7DA4NbQtqjS5bXE19a2zrXEw+jK9qOsIMbk1tDDv7j219a2zsq508PSu7j2ZmllbGRfaW5mb7Htyr6jrCBmaWVsZHPW0NPQZmllbGRzX2NvdW50uPZmaWVsZF9pbmZvoaMKPGJyPgoKbWV0aG9kc8rHttS1scewwOC78tXfvdO/2tbQyfnD97XEt723qLXEw+jK9qOsIMbk1tDDv7j2t723qMq508PSu7j2bWV0aG9kX2luZm+x7cq+o6wgbWV0aG9kc9bQ09BtZXRob2RzX2NvdW50uPZtZXRob2RfaW5mb6GjIDxicj4KCjxicj4KCtTaz8LSu8aqsqm/zdbQo6wgvau74b3pydxjbGFzc87EvP7W0LXEuPe49sr00NSjrCC+tMfrudjXoqGjCjxicj4KCjxicj4KCjxicj4KCjxicj4KCgo8cCBjbGFzcz0="cjk">更多关于深入理解Java的文章, 请关注我的专栏 : http://blog.csdn.net/column/details/zhangjg-java-blog.html
更多关于Java和Android等其他技术的文章, 请关注我的博客: http://blog.csdn.net/zhangjg_blog