JVM学习笔记——字节码指令
JVM学习笔记——字节码指令
字节码
0与 1是计算机仅能识别的信号,经过0和1的不同组合产生了数字之上的操作。另外,通过不同的组合亦产生了各种字符。同样,可以通过不同的组合产生不同的机器指令。在不同的时代,不同的厂商,机器指令组成的集合是不同的。但毕竟CPU是底层基础硬件,指令集通常以扩展兼容的方式向前不断演进。而机器码是离CPU指令集最近的编码,是CPU可以直接解读的指令,因此机器码肯定是与底层硬件系统耦合的。
问题:如果某个程序员因为不同的硬件平台需要编写多套代码,这是十分令人崩溃的。Java的使命就是一次编写、到处执行。在不同的操作系统、不同硬件平台上,均可以不用修改代码即可顺畅地执行。
如何实现JAVA跨平台?
计算机工程领域的任何问题都可以通过增加一个中间层来解决。因此,中间码应运而生,即"字节码"(Bytecode)。Java所有的指令有200个左右,一个字节(8位)可以存储256种不同的指令信息,一个这样的字节称为字节码(Bytecode)。在代码的执行过程中,JVM将字节码解释执行,屏蔽对底层操作系统的依赖;JVM也可以将字节码编译执行,如果是热点代码,会通过JIT动态地编译为机器码,提高执行效率。
字节码指令
为了方便记忆,JVM在字节码上也和汇编语言改进机器语言借助助记符来高效记忆的方法一样,设计了一套操作码助记符,使用特殊单词来标记这些数字。如ICONST_0代表00000011,即十六进制数为0x03等
字节码主要指令如下:
1.加载或存储指令
在某个栈帧中,通过指令操作数据在虚拟机栈帧的局部变量表与操作栈之间来回传输,常见指令如下:
1)将局部变量加载到操作栈中。如ILOAD(将int类型的局部变量压入栈)和ALOAD(将对象引用的局部变量压入栈)等。
2)从操作栈顶存储到局部变量表。如ISTORE、ASTORE等。
3)将常量加载到操作栈顶,这是极为高频使用的指令。如ICONST、BIPUSH、SIPUSH、LDC等。
* ICONST 加载的是-1~5的数(ICONST与BIPUSH的加载界限)。
* BIPUSH,即Byte ImmdiatePUSH,记载-128~-127之间的数。
* SIPUSH,即Short Immediate PUSH,加载-32768~32767
* LDC,即Load Constant,在-2147483618~2147483647或者字符串时,JVM采用LDC指令压入栈中。
2. 运算指令
对两个操作栈帧上的值进行运算,并把结果写入操作栈顶,如IADD、IMUL等。
3. 类型转换指令
显示转换两种不同的数值类型。如I2L、D2F等。
4.对象创建与访问指令
根据类进行对象的创建、初始化、方法调用相关指令,常见指令如下:
1)创建对象指令。如NEW、NEWARRAY等。
2)访问属性指令。如GETFIELD、PUTFIELD、GETSTATIC等。
3)检查实力类型指令。如INSTANCEOF、CHECKCAST等。
5.操作栈管理指令
JVM提供了直接控制操作栈的指令,常见指令如下:
1)出栈操作。如POP即一个元素,POP2即两个元素。
2)复制栈顶元素并压入栈。如DUP。
6. 方法调用与返回指令
常见指令如下:
1)INVOKEVIRTUAL指令:调用对象的实例化方法。
2)INVOKESPECIAL指令:调用实例初始化方法、私有方法、父类方法等。
3)INVOKESTATIC指令:调用静态类方法。
4)RETURN指令:返回VOID类型。
7.同步指令
JVM使用方法结构中的ACC_SYNCHRONIZED标志同步方法,指令集中有MONITORENTER和MONITOREXIT支持synchronized语义。
参考书籍——《码出高效》 第四章 走进JVM