Java字节码基础
目录
class文件构成
采用类似C语言的结构体来表示数据
包括两种数据类型
- 定长数据:无符号数,u1,u2,u4分别代表1个字节、2个字节、4个字节
- 不定长数据:由多个无符号数组成,通常在数据的前面给出其长度
魔数
前4个字节为魔数,十六进制表示为0xCAFEBABE,标识该文件为class文件
版本号
第5、6个字节表示次版本号,第7、8个字节表示主版本号,映射表(转为10进制后)如下
可以使用反汇编工具javap对class文件进行反汇编,然后就可以看到很多可以看得懂的文字了。
常量池
- 字面量
- 如文本字符串、final的常量值等
- 符号引用
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
访问标志
- 描述该Class是类还是接口,是否被public、abstract、final等修饰符修饰
类索引
- 描述当前类的全限定名
- 这两个字节保存的值为常量池中的索引值,根据索引值就能在常量池中找到这个类的全限定名
父类索引
- 描述父类的全限定名,跟上面类似
接口索引集合
- 含有两字节的接口计数器,描述了该类或父类实现的接口数量
- 紧接着的n个字节是所有接口的名称的字符串常量的索引值
字段表
- 字段表用于描述类和接口中声明的变量(但不包含方法内部生命的局部变量)
- 字段表也分为两部分,第一部分为两个字节,描述字段个数;第二部分是每个字段的详细信息fields_info
方法表
- 两部分组成,第一部分两个字节,描述方法个数;
- 第二部分分为每个方法的详细信息,包括方法的访问标志、方法名、方法的描述符以及方法的属性。
- 部分属性
- Code,源代码对应的JVM指令操作码
- LineNumberTable,行号表,将 Code区的操作码和源代码中的行号对应
附加属性
- 字节码的最后一部分,存放了该文件中类或接口所定义的基本信息,编译器可自由写入属性信息,因为每个编译器写入的可能都不一样,JVM会忽略不认识的属性信息。
指令
所有的指令:https://docs.oracle.com/javase/specs/jvms/se13/jvms13.pdf
分类
- 加载和存储指令
- 运算指令
- 类型转换指令
- 对象/数组创建和访问指令
- 操作数栈管理指令
- 控制转移指令
- 方法调用指令和返回指令
- 异常处理质量
- 同步控制质量
JVM指令由操作码和0至多个操作数组成
- 操作码,代表着某种特定操作含义的数组
- 操作数,操作所需参数
JVM指令集是基于栈而不是寄存器
- 字节码指令控制的是JVM操作数栈