深入虚拟机笔记之对象和数组

第15章 对象和数组

    在java虚拟机中,内存只能以对象形式在垃圾收集堆中分配。除非作为对象的一部分,否则不能为基本类型分配内存。如果需要在必须使用对象引用的场合使用基本类型,可以从java.lang包中的为基本类型分配一个包装器对象。只有对象引用和基本类型可以在java栈中以局部变量形式存在,java栈不能容纳对象。

    java虚拟机中的对象和基本类型的结构分离在java语言中体现为:对象不能作为局部变量声明,只有对象引用和基本类型可以。对象引用在声明后并不指向任何有意义的东西,只有引用在被显式初始化后,对象引用才会指向一个真实的对象。

    在java虚拟机指令集中,除了数组外,所有的对象都使用同样的操作码来实例化和存取。java中的数组是完善(full-fledged)的对象,和其他对象一样,数组是动态创建的,数组引用可以在任何需要用到引用来标识对象的地方使用,数组中对象的任何方法都可以被调用,但java虚拟机中仍然使用特殊的字节码来处理数组。如同其他对象,数组不能作为局部变量来使用,只有数组引用可以;数组对象本身通常包括基本类型数组和对象引用数组。如果声明了对象数组,数组中的成员必须通过new操作显式创建。

    对象的操作码:

    对象创建:实例化一个新对象需要通过new操作码来实现,new操作码后面紧随着两个字节的操作数,这两个字节的操作数合起来表示常量池中的一个不带符号的16位长度的索引。在特定偏移量位置的常量池入口给出了新对象所属的类型的信息。它会为这个堆中的对象(Class代表的类型数据)建立一个新的实例,用默认初始值初始化对象实例变量,然后把新对象的引用压入栈。

    对象实例变量存取:putfield和getfield操作码只在字段是实例变量的情况下才执行。putfield和getfield指令都有两个操作数,这两个操作数合起来表示常量池中的不带符号的16位索引长度的索引。设个索引指向的常量池入口包含了该字段的所属类、名字和类型等信息。putfield和getfield对对象引用进行栈操作,putfield从栈中取出实例变量值,getfield把获得的实例变量值压入栈。

 

    类变量存取:getstatic和putstatic操作码进行类变量存取操作。因为没有任何特定的对象与静态字段相关,所以getstatic和putstatic不会使用对象引用。

    类型检验:

    checkcast操作码判断栈中的对象引用是否是指定索引位置处的类或者接口的实例,如果不是,checkcast抛出一个CheckCastException异常;否则任何事情都不会发生,对象引用仍在栈中,下一条指令会接着执行。checkcast确保运行时类型转换的安全,是java虚拟机安全框架的组成部分。

    instanceof操作码从栈顶弹出对象引用,如果对象是指定索引位置处的类或者接口的实例,就向栈中压入1,否则压入0。

    数组操作码:实例化新数组可以通过newarray、anewarray和multianewarray操作码完成。

    newarray用来创建基本类型数组。基本类型由紧随newarray的单字节操作数atype指定,newarray能够创建byte、short、char、int、long、float、double和boolean类型的数组。

    当数组类型显式声明为boolean时,java虚拟机中创建数组的指令会以位为单位进行操作。在这种表示方法中,一个数组的每个boolean元素都可以使用1位来表示;当内存不是很紧张时,boolean数组可以使用byte数组的方式实现。无论虚拟机使用哪一种实现,都会使用存取byte数组元素的操作码访问boolean数组的元素。

    anewarray用来创建对象引用数组。这条指令为对象引用数组分配空间,并把数组成员的引用值初始化为null。

    multianewarray指令用来分配多维数组,所谓多维数组,就是数组的数组。多维数组也可以通过重复使用anewarray和newarray来进行分配。multianewarray指令只不过把创建多维数组的指令所需要的字节码压缩到一条指令中。

    arraylength从栈顶弹出一个数组引用,然后把这个数组的长度压入栈。

    获取数组元素:虚拟机从栈中弹出数组的索引和数组引用,再将位于给定数组的指定索引位置的值压入栈。操作byte、boolean、short时,通过符号扩展转换为int类型的值,操作char时,通过零扩展转换为int类型的值,然后把int值压入栈。

    设置数组元素:从栈中弹出要设置的值、索引和数组引用,byte、boolean只存储弹出yint类型值得低8位;short、char值只存储弹出int类型值得低16位;其他高位被直接丢弃。

 

猜你喜欢

转载自jaesonchen.iteye.com/blog/2289665