目录

Java字节码基础

class文件构成

采用类似C语言的结构体来表示数据

包括两种数据类型

  • 定长数据:无符号数,u1,u2,u4分别代表1个字节、2个字节、4个字节
  • 不定长数据:由多个无符号数组成,通常在数据的前面给出其长度

https://img.jooks.cn/img/20210224125910.png

魔数

前4个字节为魔数,十六进制表示为0xCAFEBABE,标识该文件为class文件

版本号

第5、6个字节表示次版本号,第7、8个字节表示主版本号,映射表(转为10进制后)如下

https://img.jooks.cn/img/20210224131008.png

可以使用反汇编工具javap对class文件进行反汇编,然后就可以看到很多可以看得懂的文字了。

常量池

  • 字面量
    • 如文本字符串、final的常量值等
  • 符号引用
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符

访问标志

  • 描述该Class是类还是接口,是否被public、abstract、final等修饰符修饰

类索引

  • 描述当前类的全限定名
  • 这两个字节保存的值为常量池中的索引值,根据索引值就能在常量池中找到这个类的全限定名

父类索引

  • 描述父类的全限定名,跟上面类似

接口索引集合

  • 含有两字节的接口计数器,描述了该类或父类实现的接口数量
  • 紧接着的n个字节是所有接口的名称的字符串常量的索引值

字段表

  • 字段表用于描述类和接口中声明的变量(但不包含方法内部生命的局部变量)
  • 字段表也分为两部分,第一部分为两个字节,描述字段个数;第二部分是每个字段的详细信息fields_info

https://img.jooks.cn/img/20210224142148.png

方法表

  • 两部分组成,第一部分两个字节,描述方法个数;
  • 第二部分分为每个方法的详细信息,包括方法的访问标志、方法名、方法的描述符以及方法的属性。

https://img.jooks.cn/img/20210224142429.png

  • 部分属性
    • Code,源代码对应的JVM指令操作码
    • LineNumberTable,行号表,将 Code区的操作码和源代码中的行号对应

https://img.jooks.cn/img/20210224143214.png

附加属性

  • 字节码的最后一部分,存放了该文件中类或接口所定义的基本信息,编译器可自由写入属性信息,因为每个编译器写入的可能都不一样,JVM会忽略不认识的属性信息。

指令

所有的指令:https://docs.oracle.com/javase/specs/jvms/se13/jvms13.pdf

分类

  • 加载和存储指令
  • 运算指令
  • 类型转换指令
  • 对象/数组创建和访问指令
  • 操作数栈管理指令
  • 控制转移指令
  • 方法调用指令和返回指令
  • 异常处理质量
  • 同步控制质量

JVM指令由操作码和0至多个操作数组成

  • 操作码,代表着某种特定操作含义的数组
  • 操作数,操作所需参数

JVM指令集是基于栈而不是寄存器

  • 字节码指令控制的是JVM操作数栈

示例

https://img.jooks.cn/img/20210224155240.png

https://img.jooks.cn/img/20210224155336.png