JVM 指令03__对象的创建和访问指令

一、概述

Java 是面向对象的程序设计语言,虚拟机平台从字节码层面就对面向对象做了深层次的支持,有一系列的指令专门用于对象操作,这些指令可以进一步细分为创建指令、字段访问指令、数组操作指令、类型检查指令

 

二、创建指令

虽然类实例和数组都是对象,但是 Jvm 对类实例和数组的创建却使用了不同的指令

2.1、创建类对象的指令

new: 该指令接收一个操作数,这个操作数是指向常量池的索引,该索引表示的是要创建对象的类型,new 指令执行完成之后,将创建在堆内存中对象的内存空间地址值压入操作数栈中

newarray: 创建基本类型的一维数组

anewarray: 创建引用类型的一维数组

multianewarray: 创建多维数组

案例:

三、字段访问指令

对象创建完成之后,就可以通过对象访问指令来获取对象实例的字段或数组实例中的数组元素

访问静态字段: getstatic、putstatic

访问非静态字段: getfield、putfield

getxx 指令表示将 值/对象 压入操作数栈,putxx 指令表示将 值/对象 弹出操作数栈进行操作

 

四、数组操作指令

数组操作指令主要有 xastore 和 xaload

xastore: 将数组对象的内存地址值从局部变量表加载进入操作数栈

xaload: 将操作数栈中的值保存到堆空间数组对象的指定索引位置

数据类型 加载指令 存储指令
byte / boolean baload bastore
short saload sastore
char caload castore
int iaload iastore
long laload lastore
float faload fastore
double daload dastore
reference aaload aastore

案例

public class Client {
    public static void main(String[] args) {
        int[] intArr = new int[3];
        intArr[2] = 5;
        System.out.println(intArr[2]);
    }
}

对应字节码文件

 0 iconst_3
 1 newarray 10 (int)
 3 astore_1
 4 aload_1
 5 iconst_2
 6 iconst_5
 7 iastore
 8 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
11 aload_1
12 iconst_2
13 iaload
14 invokevirtual #3 <java/io/PrintStream.println : (I)V>
17 return

指令 1、iconst_3: 将常量 3 压入操作数栈

指令 2、 newarray 10 (int): 将操作数 3 弹出操作数栈,在堆内存中为数组开辟出一块长度为 3 的空间,并且该数组元素的类型是 int,为数组进行默认初始化,完成之后将该数组空间的内存地址压入操作数栈

注 newarray 后面的 10 代表的是数组的类型,10 的类型就是 int 类型的数组,具体的官方 Jvm 指令定义类型如下

指令 3、astore_1: 将操作数栈顶的元素弹出,存入局部变量表下标为 1 的位置,该地址直接指向堆空间中数组的内存区域

指令 4、aload_1: 将局部变量表中下标为 1 的操作数压入操作数栈中

指令 5、iconst_2: 将常数 2 压入操作数栈中

指令 6、iconst_5: 将常数 5 压入操作数栈中

指令 7、iastore: 将操作数栈 5、2、0x3e86 弹出操作数栈,为数组第 2 个索引位置的元素进行显示赋值 5

通过 0x3e86 找到数组对象在堆空间的实际内存位置,2 作为数组下标索引,5 作为值为数组进行赋值操作

指令 8、getstatic: 通过符号引用 #2 在常量池中找到静态字段 System.out,并将其压入操作数栈中

指令 9、aload_1: 将局部变量表索引下标为 1 的操作数压入操作数栈

指令 10、iconst_2: 将常数 2 压入操作数栈

指令 11、iaload: 将操作数栈的栈顶操作数(2)和次栈顶操作数(0x3e86) 弹出操作数栈,通过 0x3e86 定位到数组在堆空间的实际位置,通过 2 定位到该数组索引为 2 的元素,将该元素的值压入操作数栈中

指令 12、invokevirtual #3: 通过符号引用找到常量池中对应的方法信息<println : (I)V>,main 方法栈帧中操作数弹出,接着在虚拟机栈中开辟 println 方法栈帧

输出结果 5 之后,println 方法栈帧出栈

main 方法执行完成之后 main 方法栈帧出操作数栈

堆空间的数组对象无任何引用指向,等待垃圾回收器回收

 

五、类型转换指令

类型检查指令主要有 instanceof 和 checkcast

instanceof: 判断对象是否是某一个类的实例,它会将判断后的结果压入操作数栈当中

checkcast: 检查类型是否可以进行强制类型转换,如果可以进行转换那么 checkcast 指令不会改变操作数栈,否则会抛出 ClassCastException

 

posted @ 2022-12-01 21:01  变体精灵  阅读(87)  评论(0编辑  收藏  举报