您的位置:首页 > 编程语言 > Java开发

java的class文件格式分析

2010-03-26 22:18 351 查看
1.

ClassFile


基本定义


Classfile

是一个连续的8
位字节二进制流,数据项按照顺序存储在class
文件中,相邻项没有间隔,占多字节空间的项时,高位在前。

ClassFile

文件格式是固定的,按照顺序

名称

长度

描述

备注

majic

4

个字节

魔数
:0xCAFEBABE

Od –x

命令可以看到。这样保证了
Java

虚拟机能很轻松的分辨出
Java

文件和非
Java

文件

Minor_version


major_version

分别
2

字节

主次版本号:
Class

文件格式一旦发生变化,版本号也会随之变化。

如果
class

文件版本号超出了处理范围,
java

虚拟机将不会处理该文件。

Constantpool_count,constanpool

不固定

常量池:包含了文件中类和接口相
关的常量。文字字符串、
final

变量值、类名和方法名的常量。常量池的大小平均占到了整个类大小的


60%


左右。


入口列表的形式来存储。每个常量
池入口都从一个长度为一个字节的标志开始。除了字面常量还可以容纳字段名称、方法名称和类的全限名等。

Access_flags

2

字节

访问标志
:

定义了类或接口

指明了是类还是接口、是抽象还是
具体。公共、
final

等修饰符。

This_class

2

字节

本身是一个常量池的索引,指向了
常量池中该类全限定名的常量池入口

Super_class

2

字节

指向父类全限定名

Interface_count


interfaces

不固定

该类实现的接口数量,
interfaces

包含了由该类实现的接口的常量池引用。

FiledsCount


fileds

不固定

字段数量和字段的信息表。描述了
字段的类型、描述符等。

Methods_count


Mechods

不固定

方法总数和方法本身。使用


ASM


进行
AOP


编程,通常是通过调整
Method


中的指令来实现的。


每一个方法都会有一个
Mechod_info

表,改表记录了方法的方法名、描述符、返回类型。局部变量表,字节码序列等。

Attributes_count


Attributes

不固定

属性总数和属性本身。写出了

2.class文件的结构



The ClassFile Structure

ClassFile{

u4 magic;

u2 minor_version;

u2 major_version;

u2 constant_pool_count;

cp_info constant_pool[constant_pool_count-1];

u2 access_flags;

u2 this_class;

u2 interfaces_count;

u2 interfaces[interfaces_count];

u2 fields_count;

field_info fields[fields_count];

u2 methods_count;

method_info methods[methods_count];

u2 attributes_count;

attribute_info attributes[attrributes_count];

}

说明:u2表示无符号2字节量,u4表示无符号4字节量。

各字段的说明:

magic

一般二进制文件中都有magic number这一项,这个数说明该文件是一个class文件,它的值是0xcAFEBABE。

minor_version,major_version

class文件的版本号。

constant_pool_count

常量池表中项目数加1得到。从后面的cp_info
constant_pool[constant_pool_count-1];也容易理解这个值的意思。

cp_info constant_pool[]

存储该class文件中使用到的常量信息。

access_flag

说明该class文件的访问权限和相关属性,通过位掩码来设定。

Flag Name



解释

ACC_PUBLIC

0x0001

public

ACC_FINAL

0x0010

final

ACC_SUPER

0x0020

跟调用invokespecial指令时的处理有关

ACC_INTERFACE

0x0200

这是个接口

ACC_ABSTRACT

0x0400

abastract

ACC_SYNTHETIC

0x1000

没有在源代码中出现,该类是编译器生成的

ACC_ANNOTATION

0x2000

注解类型

ACC_ENUM

0x4000

枚举类型

这些属性都很容易理解,比如我们定义一个类public final
Test{},则Test.class的access_flag中,ACC_PUBLIC和ACC_FINAL是置位的,而ACC_INTERFACE一
项肯定是0。很多类似的组合规则倒是容易自己总结出来,比如如果ACC_INTERFACE置位了,那肯定ACC_ABSTRACT也是置位的,因为接口
肯定是抽象的;如果ACC_ANNOTATION置位了,那ACC_ANNOTATION肯定同时置位,等等,诸如此类。

画一个具体的位示意图表示:



this_class

一个下标,指向常量池表中代表当前类的Constant_Class_info。

super_class

为0,或者为一个下标,指向常量池中代表其父类的Constant_Class_info。如果这个值为0,那么当前类肯定是Object类。如果
当前类是一个接口,该下标指向的是Object类的描述信息。

interface_count

该类实现的接口数,或者该接口实现的超接口数。

interfaces[]

具体的接口信息,每一项都是常量池表中的一个下标,指向表示接口的Constant_Class_info。

后面几个依次是字段(field),方法(methods)和属性的描述,不再赘述,

下面具体的分析一个class文件。源文件很简单:

public class Test{

public static void main(String[] args){

System.out.println("Hello World!");

}

}

编译,得到Test.class文件,使用WinHex打开。



前4个字节是magic部分,内容为0xCAFEBABE;随后的4个字节是class文件的版本号,这里主版本号是0x0032,也就是50,这
是使用jdk1.6编译出的class文件。再后面的2个字节是常量池表的大小信息,0x001D,也就是29,说明常量池表中一共有28项。为了方便观
察,可以使用javap -verbose Test得到的结果和当前的二进制文件进行对比。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: