小介:去年在读《深入解析JVM》的时候写的,记得当时还想着用自己的代码解析字节码的,最后只完成了一部分。现在都不知道还有没有保留着,貌似Apache有现成的BCEL工程可以做这件事。当时也只是为了学习。这份资料主要参考《深入解析JVM》和《Java虚拟机规范》貌似是1.2版本的,整理出来的。里面包含了一些自己的理解和用实际代码的测试。有兴趣的童鞋可以研究研究。嘿嘿。要有错误也希望能为小弟指点出来,感激不尽。:)
1.总体格式
| Class File format |
||
| type |
descriptor |
remark |
| u4 |
magic |
0xCAFEBABE |
| u2 |
minor_version |
|
| u2 |
major_version |
|
| u2 |
constant_pool_count |
|
| cp_info |
constant_pool[cosntant_pool_count – 1] |
index 0 is invalid |
| u2 |
access_flags |
|
| u2 |
this_class |
|
| u2 |
super_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[attributes_count] |
|
2. 格式详解
2.1 magic
magic被称为“魔数”,用来标识.class文件的开头。所有合法的.class字节码都应该是该数开头,占4个字节。
2.2 major_version.minor_version
major_version.minor_version合在一起形成当前.class文件的版本号,该版本号一般由编译器产生,并且由sun定义。如59.0。它们一起占4个字节。
2.3 constant_pool
在Java字节码中,有一个常量池,用来存放不同类型的常量。由于Java设计的目的之一就是字节码需要经网络传输的,因而字节码需要比较紧凑,以减少网络传输的流量和时间。常量池的存在则可以让一些相同类型的值通过索引的方式从常量池中找到,而不是在不同地方有不同拷贝,缩减了字节码的大小。
每个常量池中的项是通过cp_info的类型来表示的,它的格式如下:
| cp_info format |
||
| type |
descriptor |
remark |
| u1 |
tag |
|
| u1 |
info[] |
|
这里tag用来表示当前常量池不同类型的项。info中存放常量池项中存放的数据。
tag中表示的数据类型:
CONSTANT_Class_info (7)、
CONSTANT_Integer_info (3)、
CONSTANT_Long_info (5)、
CONSTANT_Float_info (4)、
CONSTANT_Double_info (6)、
CONSTANT_String_info (8)、
CONSTANT_Fieldref_info (9)、
CONSTANT_Methodref_info (10)、
CONSTANT_InterfaceMethodref_info (11)、
CONSTANT_NameAndType_info (12)、
CONSTANT_Utf8_info (1)、
注:在Java字节码中,所有boolean、byte、char、short类型都是用int类型存放,因而在常量池中没有和它们对应的项。
2.3.1 CONSTANT_Class_info
用于记录类或接口名(used to represent a class or an interface)
| CONSTANT_Class_info format |
||
| type |
descriptor |
remark |
| u1 |
tag |
CONSTANT_Class (7) |
| u2 |
name_index |
constant_pool中的索引,CONSTANT_Utf8_info类型。表示类或接口名。 |
注:在Java字节码中,类和接口名不同于源码中的名字,详见附件A.
2.3.2 CONSTANT_Integer_info
用于记录int类型的常量值(represent 4-byte numeric (int) constants:)
| CONSTANT_Integer_info |
||
| type |
descriptor |
remark |
| u1 |
tag |
CONSTANT_Integer (3) |
| u4 |
bytes |
整型常量值 |
2.3.3 CONSTANT_Long_info
用于记录long类型的常量值(represent 8-byte numeric (long) constants:)
| CONSTANT_Long_info |
||
| type |
descriptor |
remark |
| u1 |
tag |
CONSTANT_Long (5) |
| u4 |
high_bytes |
长整型的高四位值 |
| u4 |
low_bytes |
长整型的低四位值 |
2.3.4 CONSTANT_Float_info
用于记录float类型的常量值(represent 4-byte numeric (float) constants:)
| CONSTANT_Float_info |
||
| type |
descriptor |
remark |
| u1 |
tag |
CONSTANT_Float(4) |
| u4 |
bytes |
单精度浮点型常量值 |
几个特殊值:0x7f800000 => Float.POSITIVE_INFINITY、0xff800000 => Float.NEGATIVE_INFINITY、
0x7f800001 to 0x7fffffff => Float.NaN、0xff800001 to 0xffffffff => Float.NaN
2.3.5 CONSTANT_Double_info
用于记录double类型的常量值(represent 8-byte numeric (double) constants:)
| CONSTANT_Do |