字节码构成平台无关性;虚拟机构成语言无关性。
Class类文件结构
Class文件时一组以8位字节为基础单位的二进制流。其中只有两种数据类型,无符号数和表。
无符号数分为u1,u2,u4,u8分别代表1,2,4,8个字节。表是由无符号数和其他表组成。
魔数与版本
前四个字节为魔数:ca fe ba by;
后四个字节为副版本号两个字节,主版本号两个字节;
常量池
跟在主版本号后面,占用两个字节,表示常量池的常量个数,从1开始。0用来表示没有任何引用。
主要存放字面量和符号引用。
字面量类似常量,例如字符串,final声明的常量。
符号引用包括类和接口的全限定名;字段的名称和描述符;方法的名称和描述符。
共有14种表,每种表的第一位都是一个u1类型的标志位。
类型 | 标志 | 作用 | 大小 |
---|---|---|---|
class_info | 7 | 类或接口的符号引用 | u1(标志),u2(指向常量的索引) |
utf8_info | 1 | utf-8编码字符串 | u1(标志),u2(长度n),n个字节 |
访问标志
常量池结束后,紧跟着两个字节就是访问标志。
类索引,父类索引和接口索引集合
类索引为u2类型,指向常量池中常量下标。
父类索引u2类型,指向常量池中常量下标。
接口索引集合,u2表示个数,后面n个u2表示指向常量池中下标。
字段表集合
最开始一个u2表示字段个数。
包括类变量,实例变量,不包括局部变量。
u2访问修饰符,u2指向常量池常量索引(简单名称),u2指向常量池索引(描述符),u2属性个数n,n个u2属性。
全限定名:a.b.c中.改成a/b/c就是全限定名。
简单名称:变量名或者方法签名中的方法名。
描述符:方法的参数列表(数量,类型,顺序)以及返回值,字段的数据类型。
描述符都是用一个大写字母来表示。用[表示维度。
类型 | 标识 |
---|---|
byte | B |
short | S |
int | I |
long | J |
char | C |
float | F |
double | D |
boolean | Z |
void | V |
引用类型 | L |
int类型一维数组 [I , int类型二维数组 [[I .
无参无返回值方法 ()V , String method(int a, int[][] b) (I[[I)Ljava/lang/String .
字段表中不会列出父类或父接口的字段。
方法表集合
最开始一个u2表示字段个数。
u2访问修饰符,u2指向常量池常量索引(简单名称),u2指向常量池索引(描述符),u2属性个数n,n个u2属性。
如果没有重写父类方法,不会出现父类方法信息。
重载取决于方法名,参数顺序以及参数类型。
属性表
u2指向常量池名称属性;u4属性长度n;n个u1属性内容。
Code属性
抽象方法不存在Code属性。
- u2,指向常量池属性名称;
- u4,属性长度;属性长度为属性表固定长度减去名称和属性长度共u6
- u2,栈最大深度;
- u2,局部变量表空间;
- u4,字节码指令长度n;
- u1, n个u1代表字节码指令内容
- u2,异常表集合长度n;
- n个异常表;
长度 | 名称 |
---|---|
u2 | start_pc |
u2 | end_pc |
u2 | handler_pc |
u2 | catch_type |
如果start_pc和end_pc之间出现了catch_type或其子类的异常,则又handler_pc行继续处理;
如果catch_type为0是,则直接由handler_pc处理。
Exceptions属性
记录方法描述时throws关键字后面列举的异常;
长度 | 名称 |
---|---|
u2 | attribute_name_index |
u24 | attribute_length |
u2 | number_of_exceptions |
u2 | exception_index_code |
number_of_exceptions代表异常的种类;exception_index_code代表指向常量池中的class属性;
LindNumberTable属性
字节码与Java源码行号对应关系。
line_number_info由start_pc和line_numberldge u2类型属性,前者字节码行号,后者java源码行号。
LocalVariableTable属性
栈中局部变量表与Java源码中变量之间的关系。
SourceFile属性
记录源文件名称。
ConstantValue属性
只有被static修饰的变量才有这个属性;作用时为静态变量赋值。
使用final和static修饰,并且是基本数据类型或者String类型,才有ConstantValue初始化;
没有final修饰或者非基本数据类型或String类型,用方法初始化。
Innerlasses属性
记录内部类与宿主类的关系。
Derecated和Synthetic属性
Derecated标识是否不在推荐使用;Synthetic标识不是由Java源码直接产生;