Class类文件结构

今天主要记录一下JVMS中定义的标准class文件的结构1
Class文件是一组以8位字节为基础单位的二进制流,每部分都严格按照规范中的顺序出现,中间不会出现任务分隔符。对于所有占用非8字节数据项出现时,则会按高为到地位顺序进行分割进而进行存储。
##类文件结构
一个类文件都包含一下一个类文件结构,在类文件中使用类C符号结构就行表示。我们可以使用表(tables)和项(items)来描述类文件格式,表是有0个或者多个大小可变的项和表组成。具体类文件结构为:

类型名称注释
u4magic
u2minor_version
u2major_version
u2constant_pool_count
cp_infoconstant_pool[constant_pool_count-1]
u2access_flags
u2this_class
u2super_class
u2interfaces_count
u2intefaces[interfaces_count]
u2fields_count
field_infofields[fields_count]
u2methods_count
method_infomethods[methods_count]
u2attributes_count
attribute_infoattributes[attributes_count]

其中每一项具体含义如下:

  • magic number: identify the class file format,value is 0xCAFEBABE

  • minor-version, major-version:class文件的次版本号和主版本号,两者在一起决定当前class文件的版本号为major.minor,具体jdk版本号则从45开始,jdk1.1之后的每个大版本发布主版本号向上加1

  • constant_pool_count:常量池入口,是常量表中常量数加1

  • constant_pool:常量池,索引值从1开始到从常量数-1结束,此处空出0是为了满足后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项”的意思。

  • access_flags:访问标志,用于识别类或接口层次的访问信息,具体访问标志位及含义如下–
    标志名称|标志值|含义
    ----|----|----
    ACC_PUBLIC|0x0001|是否是public类型
    ACC_FINAL|0x0010|是否被声明为final,只有类可以设置
    ACC_SUPER|0x0020|是否允许使用invokespecial字节码指令,jdk1.2之后此字段编译出来为true
    ACC_INTERFACE|0x0200|标识这是一个接口
    ACC_ABSTRACT|0x0400|是否是一个抽象类型,接口和抽象类此标志为true,其他类为false
    ACC_SYNTHETIC|0x1000|标识这个类并非是有用户代码生成的
    ACC_ANNOTATION|0x2000|标识这是一个注解
    ACC_ENUM|0x4000|标识这是一个枚举

  • this_class:类索引,值指向常量池中的一个有效的Constant_Class_Info

  • super_class:父类索引,如果是类且值为0,则必须是Object类

  • interfaces_count:接口集合中接口数

  • interfaces:这个类实现了哪些接口,按源码中从左到右顺序依次列出

  • fields_count:描述字段表大小

  • fields:字段表用于描述接口或类中定义的变量,包括类级变量或实例级变量,其中每个变量结构为一个field_info

  • methods_count:描述方法表大小

  • methods:是一个类或接口中定义的方法的完整描述,方法表中每个变量结构为一个method_info,其中不包含从父类继承或者接口实现的方法

  • attributes_account:描述属性表大小
    ###constant_pool
    ####1.常量池中主要分为两大类常量

  • 字面量(Literal):

  • 符号引用(Symbolic References):主要包括一下三类–

  • 类和接口的全限定名(Fully Qualified Name):主要是针对类名和接口名, 其中类/接口名中的‘/’的由‘.’代替,eg:Thread类名java.lang.Thread会使用一个CONSTANT_Utf8_Info表示为java/lang/Thread

  • 字段的名称和描述符(Descriptor)
    主要包括三种:BaseType(B C D F I J S Z)、ObjectType(L)、ArrayType([)

  • 方法的名称和描述符:按照先参数列表,后返回值的顺序描述,参数列表按照严格的参数顺序放在一组小括号内(),即( {ParameterDescriptor} ) ReturnDescriptor,eg:Object m(int i, double d, Thread t) {…}
    可记录为(IDLjava/lang/Thread;)Ljava/lang/Object。

具体字段类型(FieldType)讨论如下:

标识字符对应类型描述
Bbyte
Cchar
Ddouble
Ffloat
Iint
Jlong
Lreference对象类型,eg:Ljava/lang/Object
Sshort
Zboolean
Vvoid
[reference数组类型,eg:java.lang.String[][]数组可记录为[[java/lang/String

####2.在常量池中常量都有一个统一的格式:
cp_info{
: u1 tag;
: u1 info[];
}

tag类型

StructureConstantTypeValue描述
Constant_utf-8_infoconstant_utf-81UTF-8编码的字符串
Constant_integer_infoconstant_integer3整型字面量
Constant_float_infoconstant_float4浮点型字面量
Constant_long_infoconstant_long5长整形字面量
Constant_double_infoconstant_double6双精度浮点型字面量
Constant_class_infoconstant_class7类或接口的符号引用
Constant_string_infoconstant_string8字符串字符量
Constant_fieldRef_Infoconstant_fieldRef9字段的字符引用
Constant_methodRef_infoconstant_methodRef10类中方法的字符引用
Constant_interfaceMethodref_infoconstant_interfaceMethodref11接口中方法的字符引用
Constant_nameAndType_infoconstant_nameAndType12字段或方法的部分字符引用
Constant_MethodHandle_infoconstant_MethodHandle15
Constant_methodType_infoconstant_methodType16
Constant_invokeDynamic_infoconstant_invokeDynamic18

对于常量池中以上类型的结构如下:

  • 对于constant_class _info、constant_string_info有相同的结构
    { u1 tag; u2 name_index};
    其中name_index是常量池中的一个constant_utf-8_info
  • 对于constant_fieldRef_info、constant_methodRef_info、constant_interfaceMethodRef_info有相同的结构:
    {u1 tag; u2 class_index; u2 name_and_type_index; }
    其中class_index必须是常量池中的一个constant_class_info,name_and_type_index必须是常量池中的一个constant_nameAndType_info
  • 对于Constant_integer_info、Constant_float_info有相同的结构
    { u1 tag; u4 bytes; }
  • 对于Constant_long_info、Constant_double_info有相同的结构
    {u1 tag; u4 high_bytes; u4 low_bytes; }
  • constant_nameAndType_info {u1 tag; u2 name_index; u2 descriptor_index; }
    其中name_index和descriptor_index都是指向常量池中的一个constant_utf-8_info,不同的是name_index表示的是一个字段或方法常量项,而descriptor_index表示的是一个字段或方法描述符
  • constant_utf-8_info{ u1 tag; u2 length; u1 bytes[length]; }

###Fields
filed_info结构为{
: u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}

  • access_flags访问权限标识名称和值对应如下:
    标识名称|值|描述
    —|----|-----
    ACC_PUBLIC|0x0001|
    ACC_PRIVATE|0x0002|
    ACC_PROTECTED|0x0004|
    ACC_STATIC|0x0008|
    ACC_FINAL|0x0010|
    ACC_VOLATILE|0x0040|
    ACC_TRANSIENT|0x0080|
    ACC_SYNTHETIC|0x1000|是否由编译器自动产生,不存在于源码中
    ACC_ENUM|0x4000|

  • name_index:指向常量池中一个constant_utf-8_info,标识一个字段的非限定名称

  • descriptor_index:指向常量池中一个constant_utf-8_info,标识一个字段的描述符

  • attributes[attributes_account]:指向一个attribute_info结构

###Methods
methods_info结构为:
{u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_account; attribute_info attributes_info[attributes_account]}

标识名称描述
ACC_PUBLIC0x0001
ACC_PRIVATE0x0002
ACC_PROTECTED0x0004
ACC_STATIC0x0008
ACC_FINAL0x0010
ACC_SYNCHRONIZED0x0020
ACC_BRIDGE0x0040A bridge method, generated by the compiler.
ACC_VARARGS0x0080方法是否接受不定参数
ACC_NATIVE0x0100
ACC_ABSTRACT0x0400
ACC_STRICT0x0800
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
  • name_index:指向常量池中一个constant_utf-8_info,只能是一个非限定名称或是和
  • 其他几项同字段表中诸项.

###Attributes
attribute_info通用结构为:{
: u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];

}

  • attribute_name_index标识属性名,是一个16位的无符号数,指向常量池中的一个constant_utf-8_info
  • attribute_length表示属性信息字节子序列的长度,不包括attribute_name_index和attribute_length这六位
  • 在jvms8中预定义了23种虚拟机能识别的属性规范,主要看常见的在jvms第二版中定义的9种类型:
    属性名称|使用位置|描述
    —|---|–
    Code|方法表|Java代码编译成的字节码指令
    ConstantValue|字段表|final关键字定义的常量值
    Deprecated|字段表、方法表、类|定义为deprecated的方法和字段
    Exceptions|方法表|方法抛出的异常
    InnerClass|类|内部类
    LineNumberTable|code属性|Java源码的行号和字节码的对应关系
    LocalVariableTable|code属性|方法的局部变量描述
    SourceFile|类文件|源文件名称
    Synthetic|字段表、方法表、类|表示方法或字段为编译器自动生成的

在类文件中有自己的数据类型集:u1,u2,u4(代表着1,2,4字节的无符号数)


  1. jvms中class file format
    http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值