机器码是CPU可以直接解读的指令,机器码是和底层硬件系统耦合的。
Java一次编写,到处执行。也就是不需要修改代码就可以在不同的操作系统、不同的硬件平台上运行。
字节码就是Java实现跨平台运行的中间层。

为什么叫字节码?

Java所有的指令有200个左右,一个字节(8位)可以存储256种不同的指令信息,一个这样的字节成为字节码。

如何执行?

JVM可以解释执行字节码,屏蔽对底层操作系统的依赖;
JVM也可以将字节码编译执行。如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率。

如何助记字节码?

纯数字表示的字节码非常难以阅读,JVM在字节码上设计了一套操作码助记符,即用特殊单词来标记这些数字。
例如:
ICONST_0代表00000011,即十六进制数0x03
ALOAD_0代表00101010,即0x2a
POP代表01010111,即0x57

ICONSTALOAD的首字母代表具体的数据类型,如A代表引用类型,I代表int类型相关操作。

字节码类型

1. 加载或存储指令

在某个栈帧中,通过指令操作数据在虚拟机栈的局部变量表操作栈之间来回传输。

  • 将局部变量加载到操作栈中。如ILOAD
  • 从操作栈顶存储到局部变量表。如ISTOREASTORE
  • 将常量加载到操作栈顶。如ICONST/BIPUSH/SIPUSH/LDC

ICONST:加载 -1 ~ 5的数。
BIPUSH:即 Byte Immediate PUSH,加载 -128 ~ 127之间的数。
SIPUSH:即 Short Immediate PUSH,加载 -32768 ~ 32767之间的数。
IDC:即 Load Constant,在 -2147483648 ~ 2147483647之间的数,或者字符串时,JVM采用LDC指令压入栈中。

2. 运算指令

对操作栈上的两个值进行运算,并把结果吸入操作栈顶,如IADD/IMUL

3. 类型转换指令

显式转换两种不同类型的数值类型。如I2L/D2F

4. 对象创建与访问指令

  • 创建对象指令。如NEW/NEWARRAY
  • 访问属性指令。如GETFIELD/PUTFIELD/GETSTATIC
  • 检查实例类型指令。如INSTANCEOF/CHECKCAST

    5. 操作栈管理指令

  • 出栈操作。如POP/POP2

  • 复制栈顶元素并压入栈。如DUP

    6. 方法调用与返回指令

  • 调用对象的实例方法。INVOKEVIRTUAL

  • 调用实例初始化方法、私有方法、父类方法等。INVOKESPECIAL
  • 调用静态方法。INVOKESTATIC
  • 返回void类型。RETURN

    7. 同步指令

    支持synchronized语义的MONITORENTER/MONITOREXIT