注意:字段表中不包含从父类或者接口中继承而来的字段,但是会添加原本代码中不存在的字段,例如this,以及内部类对外部类访问而自动添加的外部类实例字段等。
(7).method:
method_info方法表用于描述类或者接口中声明的方法,methods_count用于表示Class文件中方法总数,method方法存储了方法的访问标识、是否静态、是否final、是否同步synchronized、是否本地方法native、是否抽象方法abstract、方法返回值类型、方法名称、方法参数列表等信息。
方法的代码指令并没有直接存放在方法表中,而是存放着属性表中的方法表Code中。
注意:如果父类的方法在子类没有被重写,方法表中不会出现来自父类的方法信息,但是编译器会自动添加类构造器”
Java编译器的方法特征签名只包括:方法名称、参数顺序和参数类型,不包括方法返回值类型,因此java的方法重载不能通过方法的返回值类区别,但是在Class文件中,方法特征签名包括方法的返回值类型,因此Class文件中可以共存两个名称和参数完全相同而返回值类型不同的方法。
(8). attribute:
attribute_info属性表是Class文件格式中最具扩展性的一种数据项目,用于存放field_info字段表、method_info方法表以及Class文件的专有信息,属性表不要求各个属性有严格顺序,只要求不与已有的属性名字重复即可,属性表中存放的常用信息如下:
| 属性名称 |
使用位置 |
含义 |
| Code |
方法表 |
Java代码编译后的字节码指令 |
| ConstantValue |
字段表 |
final关键字定义的常量值 |
| Deprecated |
类、方法表、字段表 |
被声明为Deprecated的字段或方法 |
| Exception |
方法表 |
方法抛出的异常 |
| InnerClasses |
类文件 |
内部类列表 |
| LineNumberTable |
Code属性 |
java源码行号和字节码指令的对应关系 |
| LocalVariableTable |
Code属性 |
方法的局部变量描述 |
| SourceFile |
类文件 |
源文件名称 |
| Synthetic |
类、方法表、字段表 |
标识方法或字段为编译器自动生成 |
Class文件是二进制文件,使用支持二进制的文本编辑器打开之后显示的全是二进制数据,非常的不便于阅读和理解,使用JDK提供的javap工具可以简单将Class反编译,编译理解Class文件的结构,例子如下:
源码:
[java]- public class Test {
- public int getNum(int i) {
- return i + 1;
- }
- }
javap反编译之后的字节码文件:
[java]- public class Test extends java.lang.Object
- SourceFile: Test.java
- minor version: 0
- major version: 50
- //常量池
- Constant pool:
- const #1 = class #2;
- const #2 = Asciz Test;
- const #3 = class #4;
- const #4 = Asciz java/lang/Object;
- const #5 = Asciz
; //实例构造器 - const #6 = Asciz ()V; //void返回类型
- const #7 = Asciz Code; //属性表Code属性
- const #8 = Method #3.#9; //方法特征签名 java/lang/Object.
:()V - const #9 = NameAndType #5:#6;// 方法名称和返回值
:()V - const #10 = Asciz LineNumberTable; //属性表源码行号和字节码指令对应表
- const #11 = Asciz LocalVariableTable; //属性表方法局部变量表
- const #12 = Asciz this; //Test类实例对象本身
- const #13 = Asciz LTest;; //对象类型,Test类
- const #14 = Asciz getNum; //方法名称
- const #15 = Asciz (I)I; //方法参数列表为一个int类型和返回值为int类型
- const #16 = Asciz i; //参数名称i
- const #17 = Asciz I; //参数类型int
- const #18 = Asciz SourceFile;
- const #19 = Asciz Test.java;
- //方法表
- {
- //构造函数(默认构造方法)
- public Test();
- Code: //属性表Code属性
- Stack=1, Locals=1, Args_size=1
- 0: aload_0
- 1: invokespecial #8; //Method java/lang/Object.
:()V - 4: return
- LineNumberTable:
- line 2: 0
- LocalVariableTable: //属性表方法局部变量表
- Start Length Slot Name Signature
- 0 5 0 this LTest;
- //自定义方法
- public int getNum(int);
- Code:
- Stack=2, Locals=2, Args_size=2
- 0: iload_1
- 1: iconst_1
- 2: iadd
- 3: ireturn
- LineNumberTable:
- line 4: 0
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 4 0 this LTest;
- 0 4 1 i I
- }