likes
comments
collection
share

理解Class文件结构

作者站长头像
站长
· 阅读数 1

*.class 是 *.java 编译后的产物,我们来用一个最小的例子看一下class的文件结构

源代码

package sample.asm.readclass;

public class Test {
    private String name;
}

反编译

理解Class文件结构

理解Class文件结构

class文件结构(The Java Virtual Machine Specification Java SE 7 Edition)

理解Class文件结构

注意,比如cp_info,cp_info表示常量池,上图中用 constant_pool[constant_pool_count-1]的方式来表示常量池有constant_pool_count-1个常量,它 这里是采用数组的表现形式,但是大家不要误以为所有的常量池的常量长度都是一样的,其实这个地方只是为了方便描述采用了数组的方式,但是这里并不像编程语 言那里,一个int型的数组,每个int长度都一样。

(1)魔数:CAFEBABE

(2)minor_version:0000

(3)major_version:0034

理解Class文件结构

(4)常量池的数量000F (十进制:15)

理解Class文件结构

常量池的数量是constant_pool_count-1,为什么减一,是因为索引0表示class中的数据项不引用任何常量池中的常 量。

(5)常量池

理解Class文件结构

理解Class文件结构

每个常量都有一个u1类型的tag标识来表示 常量的类型,第一个常量的类型是0x0A,转换成二级制是10,有上面的关于常量类型的描述可知tag为10的常量是Constant_Methodref_info 理解Class文件结构

tagclass_indexname_and_type_index
0A0003000C
---#3(#14 java/lang/Object)#12(#6#7 ()V)

(6)u2 access_flags 0021

理解Class文件结构

表示类或者接口方面的访问信息,比如Class表示的是类还是接口,是否为public,static,final等。0x0021=0x0001|0x0020 也即ACC_PUBLIC 和 ACC_SUPER为真,其中ACC_PUBLIC大家好理解,ACC _SUPER是jdk1.2之后编译的类都会带有的标志。

(7)u2 this_class 0002

理解Class文件结构

表示类的索引值,用来表示类的全限定名称 sample/asm/readclass/Test

(8)u2 super_class:0003

理解Class文件结构

表示当前类的父类的索引值 java/lang/Object

(9)interfaces_count和 interfaces[interfaces_count]表示接口数量以及具体的每一个接口

理解Class文件结构

(10)fields_count 和 field_info

理解Class文件结构 理解Class文件结构

fields_count:1 (0001)

field_info:0002 0004 0005 0000

access_flagname_indexdescriptor_indexattribute_count
0002000400050000
---nameLjava/lang/String;0

(11)methods_count 和 method_info:

理解Class文件结构 理解Class文件结构

理解Class文件结构

access_flagname_indexdescriptor_indexattribute_countattribute_info
0001000600070001---
---<init>()V1---

接下来是attribute_info 0008对应的常量池中的常量为Code,表示的方法的Code属性,所以到这里大家应该明白方法的那些代码是存储在Class文件方法表中的属性表中的Code属性中。接下来我们在分析一下Code属性,Code属性的结构如下 理解Class文件结构

attribute_name_indexattribute_lengthmax_stackmax_localscode_lengthcode[code_length]
00080000001D00010001000000052AB70001B1
exception_table_lengthattribute_countattribute_info
00000001---

理解Class文件结构

0009,它表示常量池中属性的名称,查看常量池得知第9个常量的值为 LineNumberTable,LineNumberTable用于描述java源代码的行号和字节码行号的对应关系,它不是运行时必需的属性,如果通 过-g:none的编译器参数来取消生成这项信息的话,最大的影响就是异常发生的时候,堆栈中不能显示出出错的行号,调试的时候也不能按照源代码来设置断点,接下来我们再看一下LineNumberTable的结构如下图所示: 理解Class文件结构

attribute_name_indexattribute_length字节流
0009000000060001(有1个行号表) 0000(字节码行号0) 0003(源码行号3)

理解Class文件结构

Class文件的属性

属性数量:0001

attribute_name_indexattribute_lengthsourcefile_index
000A00000002000B
SourceFile00000002Test.java

理解Class文件结构