Java虚拟机采用基于栈的架构,其指令由操作码和操作数组成。
- 操作码:一个字节长度(0~255),意味着指令集的操作码个数不能操作256条。
- 操作数:一条指令可以有零或者多个操作数,且操作数可以是1个或者多个字节。编译后的代码没有采用操作数长度对齐方式,当处理超出一个字节的数据时,不得不在运行时从字节中重建出具体数据的结构,比如16位无符号整数需使用两个字节储存(假设为byte1和byte2),那么真实值是
(byte1 << 8) | byte2。
放弃操作数对齐操作数对齐方案:
- 优势:可以省略很多填充和间隔符号,从而减少数据量,具有更高的传输效率;Java起初就是为了面向网络、智能家具而设计的,故更加注重传输效率。
- 劣势:运行时从字节码里构建出具体数据结构,需要花费部分CPU时间,从而导致解释执行字节码会损失部分性能。
指令
大多数指令包含了其操作所对应的数据类型信息,比如iload,表示从局部变量表中加载int型的数据到操作数栈;而fload表示加载float型数据到操作数栈。由于操作码长度只有1Byte,因此Java虚拟机的指令集对于特定操作只提供有限的类型相关指令,并非为每一种数据类型都有相应的操作指令。必要时,有些指令可用于将不支持的类型转换为可被支持的类型。
对于byte,short,char,boolean类型,往往没有单独的操作码,通过编译器在编译期或者运行期将其扩展。对于byte,short采用带符号扩展,chart,boolean采用零位扩展,转换成int型的字节码来处理,相应的数组也是采用类似的扩展方式转换为i