我们在写 Java 程序的时候,比如在一个方法中创建一个对象 (Object object = new Object())。实际上这里再 Java 虚拟机中分两步:
1. Object object; // 此时在 Java 虚拟机栈中的本地变量表创建一个 reference 类型数据。
2. object = new Obejct(); // 此时在 Java 堆中创建一个实例对象为为其分配内存。
我们创建对象就是为了使用这个对象,怎么使用这个对象呢?java 程序通过在 Java 虚拟机栈中的本地变量里保存的 reference 数据来操作 Java 堆上的具体对象。我们这里要说的 Java 对象访问模式就是 reference 数据操作 Java 堆上的具体对象的方式。在 Java 虚拟机规范中只规定了 reference 类型是一个指向对象的引用,但是具体这个引用应该通过何种方式去定位、访问堆中对象的具体位置并没有详细定义,所以对象访问模式也是取决于虚拟机的实现而定的。目前主流的两种访问模式就是:句柄访问(如 c++)和直接指针访问(如 Java)两种。下面我们详细说一下这两种访问模式以及它们各自的优缺点。
句柄访问模式:

通过上图可以看到,通过句柄访问会在堆内存中划分一个称为句柄池的区域,而栈中本地变量表里的 reference 存储的就是这个对象的句柄地址,在句柄中包含了对象实例数据和对象类型数据的地址信息。这个模式的有点在于当对象被移动(垃圾收集时移动对象是非常普遍的行为)时,发生改变的是句柄中的对象实例数据指针,而栈中的 reference 不需要改变;但是由于它使用了两次指针定位,所以在速度上就会慢一些。
直接指针访问模式:

通过上图可以看到,通过直接指针访问模式 Java 虚拟机栈中的 reference 保存的直接就是对象实例数据的地址,而在对象实例数据中存储着对象类型数据地址。使用这个模式最大的好处就是速度更快,因为它节省了一次指针定位的时间开销,由于对象的访问在 Java 中非常频繁,所以这类开销积少成多后也是一项非常可观的执行成本。而我们现在 Java 大多数使用虚拟机标准都是 Sun 公司的 HotSpot,它就是使用的这种访问模式。