一、概念
虽然类实例和数组都是对象,但 Java 虚拟机对类实例和数组的创建与操作使用了不同的字节码指令:
- 创建类实例的指令:new
- 创建数组的指令:newarray,anewarray,multianewarray
- 访问类字段(static 字段,或者称为类变量)和实例字段(非 static 字段,或者成为实例变量)的指令:getfield、putfield、getstatic、putstatic
- 把一个数组元素加载到操作数栈的指令:baload、caload、saload、iaload、laload、faload、daload、aaload
将一个操作数栈的值储存到数组元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore
- 取数组长度的指令:arraylength
- 检查类实例类型的指令:instanceof、checkcast
二、案例
- 源代码:
package jvm; public class ObjectCreate { public static void main(String[] args) { User user = new User(); User[] users = new User[5]; int [] ages = new int[7]; } } class User { private String userName; private Integer age; }
- 字节码指令分析如下图:
- tip: 3:dup 中dup的使用原因:new字节码指令的作用是创建指定类型的对象实例、对其进行默认初始化,并且将指向该实例的一个引用压入操作数栈顶;
-
然后因为invokespecial会消耗掉操作数栈顶的引用作为传给构造器的“this”参数,所以如果我们希望在invokespecial调用后在操作数栈顶还维持有一个指向新建对象的引用,就得在invokespecial之前先“复制”一份引用——这就是这个dup的来源。
三、案例(2)
- 源码如下:
package jvm; public class ObjectCreate { public static void main(String[] args) { User user = new User(); User[] users = new User[5]; int [] ages = new int[7]; user.userName = "admin"; String name = user.userName; } } class User { String userName; Integer age; }
- 字节码指令分析如下,: