A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 荣凯旋 黑马帝   /  2012-1-28 12:59  /  2499 人查看  /  2 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

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, 所有的字符串都由它存储表示。包括文字字符串、全限定名、字段名、方法名、描述符等都指向它。

2 个回复

正序浏览
是呀 存的资料
回复 使用道具 举报
是转载的吧,自己写就厉害了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马