JVM——对象的访问定位

在java程序中,我们访问对象的操作是非常频繁的。下面来介绍一下访问对象操作在内存中的对应过程。

        我们知道,对象实例是存放在java堆中的,而我们new对象时,用一个变量接收新创建的对象,这个变量实际是存在java虚拟机栈中的,既然两个东西不在一个空间里,那怎么使用呢?

        我们在程序中顶一个变量接收对象,这个变量其实就是虚拟机栈中的reference数据,这个reference存放的内容是一个地址。是指向对象的地址,但是虚拟机并没有定义这个引用应该通过什么方式去定位对象,或者说是去访问对象。用什么方式就取决于虚拟机的具体实现。目前主流的访问方式有两种:句柄和直接指针。

        句柄访问方式:Java堆中会分出一块内存,创建一个句柄池,这种方式下,reference指向的就是对象的得句柄池的地址,句柄池中包含对象的实例数据和类型数据的具体地址。如下图所示:

JVM——对象的访问定位

        reference中存放的地址指向对象的句柄池,句柄池中存放对象的实例数据地址和对象类型数据的指针,再通过句柄池中的对象实例数据指针到实例池(java堆)中找到对象实例数据,通过对象类型数据的指针到方法区中找到对象的数据类型。通过这种方式实现对对象的访问和操作。

        直接指针式访问:这种方式访问对象,reference存放的地址直接就是对象地址,指向java堆中存放的对象,在这个对象中还存放了对象类型数据的指针,然后在通过指针在方法区中找到对象的类型数据。如下图所示:

JVM——对象的访问定位

        这就是内存中直接指针方式访问对象的过程,reference的地址指向java堆中的对象实例数据,在对象实力数据中存储了对象类型数据的指针,指向方法区中的对象类型数据。

两种方式的比较:

        句柄方式访问对象,因为reference中存放的是稳定的句柄池的地址,对象发生移动时(例如对象被垃圾回收器回收在内存中就会发生移动),只需要改变句柄中的实例数据指针,而reference本身不需要修改。

        使用直接指针的方式访问对象时,最大的优点就是速度快,因为这种方式省去了一次向实例数据寻址的时间,java中对对象的访问是十分频繁的,积少成多,节省下来的时间成本就是十分可观的。Sun Spot 虚拟机就是采用的这种方式。