Java Class文件结构分析
学习 Java 虚拟机对于理解 AOP ,反射,并发同步、垃圾回收、代码优化等方面都会有不少帮助,有时候还是有必要对底层的原理做一下了解。不过看起来确实比较费解。可以一步一步来,能看懂多少是多少。
Java 虚拟机可以从 class 字节码文件、类装载体系结构、对象生命周期、执行引擎、 API 规范等几个方面来学习。 Class 文件是 java 虚拟机的基础,从 class 文件结构中可以学习到 java 虚拟机的一些基本原理。
本文主要介绍 class 文件的设计结构,为后面的话题打下一个基础。 ( 主要参考了深入 java 虚拟机这本书和网上资料 )
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. CLassFile 详细结构
根据如上格式定义成结构体如下
( 以下内容参考了文章 http://hi.baidu.com/52dege/blog/item/f33a3cf4092491dbf3d3854f.html ) :
ClassFile {
u4 magic; // 必须为 : 0xCAFEBABE
u2 minor_version;
u2 major_version; //CLASS 文件结构主次版本号 JAVA2 支持 45.0-46.0
u2 constant_pool_count; // 记录常量信息
cp_info constant_pool[constant_pool_count-1]; // 计数从 1 开始
u2 access_flags; //class/interface 访问权限
u2 this_class; // 指向 constant_poll 中的有效索引值
u2 super_class; //0 或指向 constant_poll 中的有效索引值 , 对于 interface 必须为非 0
u2 interfaces_count; //superinterfaces 的个数
u2 interfaces[interfaces_count]; // 计数 [0,count-1) 对应 constant_pool 中的一个索引值
u2 fields_count;
field_info fields[fields_count]; // 主要用于记录 class 及实例中的变量
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
对于上面的 cp_info constant_pool[constant_pool_count-1], 是一个 cp_info 结构体的系列。
cp_info {
u1 tag;
u1 info[];
}
在 java 虚拟机规范里面一共定义了 12 种 cp_info , tag 值从 1 到 12 :
CONSTANT_Utf8 1
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long 5
CONSTANT_Double 6
CONSTANT_Class 7
CONSTANT_String 8
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_NameAndType 12
( 好像没有 2 ???书上暂时也没看到。 )
对应的 cp_info 结构分别如下:
CONSTANT_Utf8
CONSTANT_Utf8_info {
u1 tag; //tag 值等于 1
u2 length;
u1 bytes[length];// 存储字符串数组
}
这是非常核心的一个 cp_info, 所有的字符串都由它存储表示。包括文字字符串、全限定名、字段名、方法名、描述符等都指向它。
|
|