Class类文件结构
在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。 编译生成了class文件(字节码): u代表无符号数。
魔数与class文件的版本
每个 Class 文件的头 4 个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接收的 Class 文件。 紧接着魔数的四个字节存储的是 Class 文件的版本号:第 5 和第 6 位是次版本号,第 7 和第 8 位是主版本号。 每当 Java 发布大版本(比如 Java 8,Java9)的时候,主版本号都会加 1。你可以使用 javap -v 命令来快速查看 Class 文件的版本号信息。 34的16进制就是52。 高版本的 Java 虚拟机可以执行低版本编译器生成的 Class 文件,但是低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。
常量池
紧接着主次版本号之后的是常量池,常量池的数量是 constant_pool_count-1(常量池计数器是从 1 开始计数的,将第 0 项常量空出来是有特殊考虑的,索引值为 0 代表“不引用任何一个常量池项”)。 常量池主要存放两大常量:字面量和符号引用。
访问标志(Access Flags)
在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为 public 或者 abstract 类型,如果是类的话是否声明为 final 等等。
当前类(This Class)、父类(Super Class)、接口(Interfaces)索引集合
类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。 接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 implements后的接口顺序从左到右排列在接口索引集合中。 类名为HelloWorld,父类Object,没有接口。
字段表集合(Fields)
1:文件的字段的个数为1; 2:access_flags: 字段的作用域为public 3:name_index: 对常量池的引用,字段的名称为a 4:descriptor_index: 对常量池的引用,表示字段和方法的描述符为int 5:存放属性的个数为0
方法表集合(Methods)
上1:有两个方法,一个是构造方法,一个是add。 上2和下1:表示public 上3和下2,上4和下三,分别代表方法名和描述符,一个为空,一个是int,一个变量个数为0,一个变量个数为2: 上5和下4表示有一个属性表。
属性表集合(Attributes)
上1和下1:表示有一个属性表。 上2和下2:表示属性表为Code
字节码指令简介
方法体的内容和指令:
字节码与数据类型
这个i就是表示的数据类型就是整型。
加载指令
将局部变量表中1加载到操作数栈,然后将2加载到操作数栈,将3从操作数栈存储到局部变量表,将常量2加载到操作数栈。
运算指令
类型转换指令
整型转化为长整型。
对象创建与访问指令
操作数栈指令
控制转移指令
不符合就跳转到20行,获得输出流,输出字符串。符合就继续执行,利用goto跳转到28行。
方法调用和返回指令
异常处理指令
同步指令
|