java class 字节码
java class 字节码
协议:
- class文件
- 魔数(Magic):4byte -> 0xCAFEBABE 类似2f3f
- 版本(Version):4Byte -> 0x00000034 前两个次版本, 后两个主版本 -> 1.8(内部版本52)
- 常量池(Constant Pool):
- 常量池计数器:2byte
- 常量池计数区:tag + length + bytes或者如下14种:
- 访问标志(Access Flag): 2byte
- 当前类名索引(This Class):2byte-> 常量池索引
- 父类名索引(Super Class):2byte
- 接口索引(interfaces):
- 接口计数器:2byte
- 接口名称索引 n个
- 字段表(fields):字段表用于描述类和接口中声明的变量,包含类级别的变量以及实例变量,但是不包含方法内部声明的局部变量
- 方法表(method):
- 方法的属性
- “Code区”:源代码对应的JVM指令操作码,在进行字节码增强时重点操作的就是“Code区”这一部分。
- “LineNumberTable”:行号表,将Code区的操作码和源代码中的行号对应,Debug时会起到作用(源代码走一行,需要走多少个JVM指令操作码)。
- “LocalVariableTable”:本地变量表,包含This和局部变量,之所以可以在每一个方法内部都可以调用This,是因为JVM将This作为每一个方法的第一个参数隐式进行传入。当然,这是针对非Static方法而言。
- 方法的属性
- 附加属性(attributes):字节码的最后一部分,该项存放了在该文件中类或接口所定义属性的基本信息
字节码操作集合
- 上图0~17,就是.java中的方法源代码编译后让JVM真正执行的操作码。
- 为了帮助人们理解,反编译后看到的是十六进制操作码所对应的助记符,十六进制值操作码与助记符的对应关系,以及每一个操作码的用处可以查看Oracle官方文档进行了解,在需要用到时进行查阅即可。
- 比如上图中第一个助记符为iconst_2,对应到图2中的字节码为0x05,用处是将int值2压入操作数栈中。
- 以此类推,对0~17的助记符理解后,就是完整的add()方法的实现。
操作数栈和字节码
- JVM的指令集是基于栈而不是寄存器,基于栈可以具备很好的跨平台性(因为寄存器指令集往往和硬件挂钩)
- 缺点在于,要完成同样的操作,基于栈的实现需要更多指令才能完成
- 由于栈是在内存实现的,而寄存器是在CPU的高速缓存区,相较而言,基于栈的速度要慢很多,这也是为了跨平台性而做出的牺牲
- 上文所说的操作码或者操作集合,其实控制的就是这个JVM的操作数栈
- 实例如下:

参考&学习:
字节码增强技术探索

浙公网安备 33010602011771号