classfile解析

class结构

Class文件是一组以8个字节为基础单位的二进制字节流。各项数据会严格的按照顺序紧凑的排列在class文件中中间没有分隔符,使得class文件存储的内容几乎全部都是程序运行的。
Java虚拟机规范规定的,class文件格式采用的类似C语言的结构体的伪结构来存储的,这种结构只有两种数据类型。 无符号数 和 表

无符号数: 属于基本数据类型 主要用于描述数字 索引符号 数量值 或者按照UTF-8编码构成的字符串值 数据类型 U1 U2 U4 U8
也只是逻辑上的区分。 u1 —表示一个字节 u2 —表示两个字节 U4 — 依次类推 u8 —依次类推
表:由多个无符号数或者其他表作为数据项构成的复合数据类型。所有的表都习惯以_info结尾 表主要用于描述有层次关系的复合结构数据。比如方法、字段 需要注意的是class文件没有分隔符,所以每个二进制数据类型都是严格定义的 具体的顺序如下:

在这里插入图片描述

1.1 魔数

1 .每一个class文件的头4个字节 被称为魔数 magicNumber
2 . 唯一用于确定这个文件是否为一个能被虚拟机接受的class文件
3.Class文件魔数值为0xCAFEBABE 如果以个文件不是以CAFEBABE开头,那么它就肯定不是java的class文件。

很多的文件存储标准中都使用魔数来识别文件的身份。 譬如图片格式.gif 或
jpeg等在文件的头部都存有魔数,使用魔数而不是文件的扩展名称来判断 ,这种情况是处于安全的考虑。

1.2 class文件版本号

紧挨着魔数的4个字节表示class的文件的版本号 版本号:
1.次版本号 --minor_version 前2个字节用于表示次版本号
例如:00 00
2.主版本号 --major_version 后2个字节用于表示主版本号
例如: 00 34

这个版本号随着jdk版本的不同而表示不同版本的范围。Java的版本号是从45开始的
如果class的版本号超过虚拟机的版本 会被拒绝执行。

JDK1.2 ----0X002E 46
JDK1.3 ----0X002F 47
JDK1.4 ----0X0030 48
JDK1.5 ----0X0031 49
JDK1.6 ----0X0032 50
JDK1.7 ----0X0033 51
JDK1.8 ----0X0034 52

1.3 常量池

CONSTANT_POOL_COUNT和CONSTANT_POOL
紧跟着魔数与版本号之后的是常量池入口,常量池简单理解为class文件的资源库。

  • 它是class文件结构中与其他项目关联最多的数据类型
  • 是占用class文件空间最大的数据项目之一
  • 是在文件中第一个出现的表类型数据项目。

常量池的数量是不固定,所以在常量池的入口需要放置一个u2类型的数据,代表常量池的计数值CONSTANT_POOL_COUNT。
CONSTANT_POOL_COUNT 从1开始计数的。 class文件结构中只有常量池的容量计数是从1开始的。第0项腾出来满足后面某些指向常量池的索引值的数据,在特定的情况下需要表达“不引用任何一个常量池项目” 把索引值的第0项留给JVM自己用。
CONSTANT_POOL是没有索引值为0的入口的,但是在CONSTANT_POOL_COUNT缺失的第0项也是要被计算在内的。
比如CONSTANT_POOL 中有14项 那么CONSTANT_POOL_COUNT的数值就是15

常量池中主要存放两大类常量:

1.字面量: 比较接近java语言层面的常量的概念 比如 字符串 被final关键字声明的常量值。
2.符号引用: 属于编译原理方面的概念 包括三项。

  • 类和接口的全名
  • 字段的名称和描述符
  • 方法的名称和描述符

在加载class文件的时候 是进行动态连接的。在class文件中不会保存各个方法和字段的最终内存布局信息。(需要经过转换) 当虚拟机运行时 需要从常量池获得对应的符号引用,再在类创建时或者运行时解析并翻译到具体的内存地址中。

CONSTANT_POOL_COUNT 占2个字节 本例中为0x20 转换成十进制为32 说明常量池中有31个常量 ----从1开始计数 其他集合类型均从0开始。 索引值为1-31 第0项常量具有特殊意义。

CONSTANT_POOL 表示的是类型数据集合,在该常量池中,每一项常量都是一个表 共有14种 -----JDK1.7版本,这14种结构的表都是不相同的结构数据。14个表都有一共同的特点,都是由u1的标志位开始的,可以通过这个标志位来判断这个常量属于哪种常量的类型。
在这里插入图片描述

2.2.4 access_flag

用于表示对该类或接口的访问权限以及该类或接口的属性
在这里插入图片描述

2.2.5 this_class

该this_class 项目的值 必须是constant_pool表中的有效索引,该constant_pool索引处的条目必须是表示此文件定义的类或接口 CONSTANT_Class_info 结构class

2.2.6 super_class

必须是constant_pool表中的有效索引, 如果super_class的值不为0 则constant_pool中的条目必须为CONSTANT_Class_info 结构 这个结构表示此类的文件定义的类的直接超类。直接超类不能在其classfile结构的access_flag项中设置 ACC_FINAL 标志。其实要描述的意思就是说 如果superclass指代的超类,那么它就不能被final修饰。

2.2.7 常量池详细解析常量类型

  • 编号1: CONSTANT_UTF8_INFO TAG1 ------占用一个空间字节 Length: utf-8字符串占用的字节数 Bytes 长度为length字符串 用于表示utf-8的编码的字符串
  • 编号3 CONSTANT_integer_info Tag3 Bytes 4个字节 Big_Endian(高位在前) 存储int类型的值
  • 编号4 CONSTANT_float_info Tag4 Bytes 4个字节 Big_Endian(高位在前) 存储float类型的值
  • 编号5 CONSTANT_long_info Tag5 Bytes 8个字节 Big_Endian(高位在前) 存储long类型的值
  • 编号6 CONSTANT_double_info Tag6 Bytes 8个字节 Big_Endian(高位在前) 存储double类型的值
  • 编号7 CONSTANT_Class_info Tag7 Index 2个字节 指向类的全限定名的项的索引 类和接口符号引用
  • 编号8 CONSTANT_String_info Tag8 Index 2个字节 指向字符串的字面量的索引
  • 编号9 CONSTANT_Fieldref_info Tag9 Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项 Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
    字段的符号引用
  • 编号10 CONSTANT_Methodref_info Tag10 Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项 Index 2个字节 指向字段描述符CONSTANT_NameAndType的索引项
    类中方法的符号引用
  • 编号11 CONSTANT_InterfaceMethodref_info Tag11 Index 2个字节 指向声明字段的类或接口的描述符 CONSTANT_Class_info的索引项 Index 2个字节
    指向字段描述符CONSTANT_NameAndType的索引项 接口中方法的符号引用
  • 编号12 CONSTANT_NameAndType Tag12 Index 2个字节 指向该字段或方法名称常量项的索引 Index 2个字节 指向该字段或方法描述符常量项的索引 字段或方法的符号引用
  • 编号15 CONSTANT_MethodHandler_info Tag15 Reference_kind 1个字节 1-9之间的一个值 决定了方法句柄的类型。方法句柄类型的值表示方法句柄的字节码行为 Reference_index 2个字节
    对常量池的有效索引。 表示方法句柄
  • 编号16 CONSTANT_MethodType_info Tag16 Descriptor_index 2个字节 指向UTF8_info 结构表示的方法描述符
  • 编号18CONSTANT_InvokeDynamic_info Tag18 Bootstrap_method_attr_index: 2个字节 当前class文件中引导方法表的bootstrap_methods[] 数组的有效索引 Name_and_type_index:
    2个字节 指向NameAndType_info 表示方法名和方法描述符。 表示动态方法的调用点。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值