field_info、method_info 与 attribute_info

field_info 数据结构伪代码

field_info{
    u2 access_flags;
    u2 name_index;
    u2 descriptor_index;
    u2 attributes_count;
    attribute_info attributes[ attributes_count ];
}

method_info 数据结构伪代码

method_info{
    u2 access_flags;
    u2 name_index;
    u2 descriptor_index;
    u2 attributes_count;
    attribute_info attributes[ attributes_count ];
}


Class 的 access_flags

标志名称 取值 说明
ACC_PUBLIC 0x0001 public 类型
ACC_FINAL 0x0010 final 类型
ACC_SUPER 0x0020 用于 invokespecial 指令
ACC_INTERFACE 0x0200 表明这个类是一个 Interface
ACC_ABSTRACT 0x0400 abstract 类型
ACC_SYNTHETIC 0x1000 表明该类由编译器根据情况生成的,源码里无法显示定义这样的类。
ACC_ANNOTATION 0x2000 注解类型
ACC_ENUM 0x4000 枚举类型


Field 的 access_flags

标志名称 取值 说明
ACC_PUBLIC 0x0001 public 类型
ACC_PRIVATE 0x0002 private 类型
ACC_PROTECTED 0x0004 protected 类型
ACC_STATIC 0x0008 static 类型
ACC_FINAL 0x0010 final 类型
ACC_VOLATILE 0x0040 volatile 类型
ACC_TRANSIENT 0x0080 transient 类型,说明该成员不能被串行化。
ACC_SYNTHETIC 0x1000 表明该类由编译器根据情况生成的,源码里无法显示定义这样的类。
ACC_ENUM 0x4000 枚举类型


Method 的 access_flags

标志名称 取值 说明
ACC_PUBLIC 0x0001 public 类型
ACC_PRIVATE 0x0002 private 类型
ACC_PROTECTED 0x0004 protected 类型
ACC_STATIC 0x0008 static 类型
ACC_FINAL 0x0010 final 类型
ACC_SYNCHRONIZED 0x0020 synchronized 函数
ACC_BRIDGE 0x0040 桥接方法,由编译器根据情况生成。
ACC_VARARGS 0x0080 可变参数个数的函数。
ACC_NATIVE 0x0100 native 函数
ACC_ABSTRACT 0x0400 抽象函数
ACC_STRICT 0x0800 strictfp 类型(strict float point,精确浮点)
ACC_SYNTHETIC 0x1000 表明该成员由编译器根据情况生成的,源码里无法直接定义这样的成员。
也被称为合成函数,内部类访问外部类的私有成员时,在class文件中也会生成一个 ACC_SYNTHETIC 修饰的函数。




attribute_info

attribute_info 数据结构伪代码

attribute_info {
    u2 attribute_name_index;        // 属性名称,指向常量池中(constant_pool)Utf8常量项的索引。
    u4 attribute_length;            // 该属性具体内容的长度,下面info的数组长度。
    u1 info[ attribute_length ];    // 属性具体内容。这里是泛指,不同的属性,这里不一样。
}

与常量池类型不一样的是,属性是由其名称来区别的,即 attribute_info 中的 attribute_name_index 所指向的 Utf8 字符串。

attribute_name_index 字符表

属性名称和作用

名称 说明
"ConstantValue" 该属性只出现于 field_info 中。
用于描述一个常量成员域(long、float、double、int、short、char、byte、boolean、String等)的值。
"Code" 该属性只出现于 method_info 中,用于描述一个函数(非 native 和 abstract 的函数)的内容。
源码中该函数内容编译后得到的虚拟机指令,try/catch 语句对应的异常处理表等。
"Exceptions" 当一个函数抛出异常(Exception)或错误(Error)时,这个函数的 method_info 将保存此属性。
"SourceFile" 包含一个指向 Utf8 常量项的索引,包含此 Class 对应的源码文件名。
"LocalVariableTable" 包含在 "Code" 属性中的属性,用来描述一个函数的本地变量相关的信息。
比如变量名称,在源码中对应的行号。

Code 属性

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;    // pc (program counter)
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[ exception_table_length ];
    
    u2 attributes_count;
    attribute_info attributes[ attributes_count ];
    
    ......
}

attribute_name_index

指向内容为 "Code" 的 CONSTANT_Utf8_info 常量项。

attribute_length

表示接下来内容的长度。

max_stack

用于说明这个函数在执行过程中,需要最深多少栈空间(栈项)。
JVM执行一个指令的时候,该指令的操作数存储在一个名为“操作数栈(operand stack)”的地方。
每一个操作数占用一个或两个(long、double 类型操作数)栈项。
stack是一块只能进行先入后出的内容。

max_locals

表示该函数最多包括几个局部变量。

code_length

代表 code 数组的长度。

code

函数对应的指令内容,也就是函数的源码经过编译器转换后得到的 Java指令码 存储在 code数组 中。

exception_table_length

表示函数中,异常表的长度。

exception_table

异常表,一个函数可以包含多个 try/catch 语句,一个 try/catch 语句对应 exception_table 数组中的一项。

start_pc

描述 try/catch 语句从哪条指令开始。code[ code_length ] 数组中。

end_pc

表示这个 try 语句到哪条指令结束(不包括 catch)。

handler_pc

表示 catch 语句的内容从哪条指令开始。

catch_type

表示 catch 中截获的 Exception 或 Error 的名字,指向 CONSTANT_Utf8_info 常量项。
如果 catch_type 取值为0,则表示它是 final{ } 语句块。

LineNumberTable

用于调试,指明指令对应的源码行号。
主要靠其结构里面的 start_pc 和 line_number

LineNumberTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;
    
    {
        u2 start_pc;        // 指向 Code_attribute 中 code 数组某处指令
        u2 line_number;     // 指明 start_pc 位于源码的哪一行。
    } line_number_table[ line_number_table_length ];
    
}

LocalVariableTable

用于调试,调试时可以用于计算本地变量值。

LocalVariableTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_table_length;
    
    {
        u2 start_pc;            // 指向 Code_attribute 中 code 数组某处指令
        u2 length;              // 指令长度
        u2 name_index;          // 此局部变量的名称,指向 CONSTANT_Utf8_info 常量项。
        u2 descriptor_index;    // 此局部变量的类型,指向 CONSTANT_Utf8_info 常量项。内容为 Field Descriptor 字符串描述符。
        u2 index;
    } local_variable_table[ local_variable_table_length ];
}




©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、Class 文件结构初识 “与平台无关” 的理想最终实现在操作系统的应用层面上:众多虚拟机厂商发布了许多可以运...
    凯玲之恋阅读 1,107评论 0 1
  • 成为一名优秀的Android开发,需要一份完备的知识体系[https://github.com/Android-A...
    字节跳不动阅读 1,176评论 1 1
  • 一、class文件结构 class文件用文本编辑器打开: 字节码文件是由 十六进制值组成 的,对于 JVM 来说,...
    R7_Perfect阅读 393评论 0 1
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 8,017评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    余生动听阅读 10,993评论 0 11

友情链接更多精彩内容