- Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码) 以及 跟随其后的零至多个代表此操作所需的参数(称为操作数)构成。
- 大多数指令都不包括操作数,只有一个操作码,指令参数都存放在操作数栈中。
- 劣势
- 字节码指令集,由于Java虚拟机操作码的长度为一个字节,这意味着指令集的操作码总数不能够超过256条。
- Class文件格式放弃了编译后代码的操作数长度对齐,这就意味着虚拟机在处理那些超过一个字节的数据时,不得不在运行时从字节中重建出具体数据的结构。
- 优势
- 放弃了操作数长度对齐,就可以省略大量的填充和间隔符号。
- 用一个字节来代表操作码,尽可能获得短小精干的编译代码。
1. 字节码与数据类型
- 在Java虚拟机的指令集中,大部分指令都包括其操作符对应的数据类型信息。
- iload指令:用于从局部变量表中加载int类型的数据到操作数栈中。
- fload指令:用于从局部变量表中加载float类型的数据到操作数栈中。
- 对于大部分与数据类型相关的字节码指令,它们的操作码助记符中都有特殊的字符来表示专门为哪种数据类型服务。i代表int、s代表short、b代表byte、f代表float、a代表reference。
2. 加载和存储指令
- 加载和存储指令用于将数据在栈帧中的布局变量表和操作数栈之间来回传输。
3. 运算指令
- 算术指令对操作数栈上的两个值进行某种特定运算,并把结果重新存入到操作数栈顶。
- 大体上运算指令可以分为 对整形数据的运算 和 对浮点型数据的运算
4. 类型转换指令
- 类型转换指令可以将两种不同的数值类型相互转换,这些转换操作一般用于实现用户代码中的显示类型转换操作。
- Java虚拟机支持以下数值类型的宽化类型转换,即小范围向大范围类型的安全转换。
- int类型到long、float或者double类型
- long类型到float、double类型
- float类型到double类型
- 反之,处理窄化类型转换时,就必须显示地使用转换指令来完成,这些转换指令包括i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l和d2f。
- 但是窄化类型转化可能会导致转换结果产生不同的正负号、不同的数量级情况、转化过程可能导致数值的精度损失。 但是*中明确规定数据类型的窄化转换指令永远不可能导致虚拟机抛出运行时异常。
5. 对象创建与访问指令
- 虽然类实例和数组都是对象,但是Java虚拟机为他们的创建与操作使用了不同的字节码指令。
- 对象创建之后,就可以通过访问指令来获取对象实例 或者 数组实例中的字段或者数组元素。
6. 操作数栈管理指令
- Java虚拟机也挺了一些直接用于操作操作数栈的指令
7. 控制转移指令
- 可以让Java虚拟机有条件或无条件地从指定位置指令的下一条指令继续执行程序。
- 可以认为控制指令就是在条件或者无条件地修改PC寄存器的值。
8. 方法调回和返回指令
- 方法调用(分派、执行过程)在第8章具体介绍。
- 方法调用指令与数据类型无关,但是方法返回指令是根据返回值的类型区分的。 ireturn、lreturn、freturn、dreturn、areturn
- 还有一条return指令,供声明为void的方法、实例初始化方法、类和接口的类初始化方法使用。
9. 异常处理指令
- 在Java中显式抛出异常的操作都有athrow指令来实现。
- 而在Java虚拟机中,异常处理(catch语句)不是由字节码指令来实现的,而是采用异常表来完成的。
10. 同步指令
- Java虚拟机可以支持方法级的同步和方法内部一段指令序列的同步。 这两种同步结构都是使用锁来实现的。
- 对于方法级的同步:不是通过字节码指令来控制的,它实现在方法调用和返回操作之中。虚拟机可以在方法表结构中的访问标志得到当前方法是否被声明为一个同步方法。
- 同步一段指令序列:通常使用synchronized语句块来表示,Java虚拟机中用monitorenter和monitorexit两条指令来支持synchronized关键字的语义。