class文件解析
-
javap是jdk自带的反解析工具,它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
-
有些信息(如本地变量表、指令和代码行偏移量映射表、常量池中方法的参数名称等等)需要在使用javac编译成class文件时,指定参数才能愉出
,如果你使用javac -g xx.java就可以生成所有相关信息了 -
使用的eclipse.则默认情况下,eclipse在编译时会帮你生成局部变量表、指令和代码行偏移量映射表等信息的。
-
通过局部变量表,我们可以查看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用等信息
- 通过javap命令可以查看一个java类反汇编得到的Class文件版本号、常量池、访问标识、变量表、指令代码行号表等信息
- 不显示类索引、父类索引、接口索引集合、<clinit>O 、<init>()等结构
- 通过对前面例子代码反汇编文件的简单分析,可以发现,一个方法的执行通常会涉及下面几块内存的操作:
- java栈中:局部变量表、操作数栈
- java堆:通过对象的地址引用去操作
- 常量池
- 其他:帧数据区、方法区的剩余部分等情况
字节码
- Java字节码对于虚拟机,就好像汇编语言对于计算机,属于基本执行指令
- Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(操作码,Opcode)以及紧跟其后的0到多个代表此操作所需参数(操作数,Operands)构成
- Java虚拟机采用面向操作数栈而不是寄存器结构,所以大多数指令不包含操作数,只有操作码
- 指令集的操作码为1字节
字节码与数据类型
-
Java虚拟机的指令集中,大多数的指令都包含了其操作所对应的数据类型信息,
iload
指令用于从局部变量表中加载int
型的数据到操作数栈中,而fload
指令加载的则是float
类型的数据。 -
对于大部分与数据类型相关的字节码指令,它们的操作码助记符中都有特殊的字符来表明专门为哪种数据类型服务:
- i:int
- l:long
- s:short
- b:byte
- c:char
- f:float
- d:double
-
有一些指令的助记符中没有明确地指明操作类型的字母,如
arraylength
指令,它没有代表数据类型的特殊字符,但操作数永远只能是一个数组类型的对象
-
无条件跳转指令goto则是与数据类型无关的。
-
大部分的指令都没有支持整数类型byte、char和short,甚至没有任何指令支持boolean类型
-
编译器会在编译期或运行期将byte和short类型的数据带符号扩展(Sign-Extend)为相应的int类型数据,将boolean和char类型数据零位扩展(Zero-Extend)为相应的int类型数据
-
处理boolean、byte、short和char类型的数组时,也会转换为使用对应的int类型的字节码指令来处理。因此,大多数对于boolean、byt