对象的访问定位
建立对象就是为了使用对象,我们的Java程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式有虚拟机实现而定,目前主流的访问方式有①使用句柄和②直接指针两种:
-
句柄: 如果使用句柄的话,那么Java堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息;
息
-
直接指针: 如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference 中存储的直接就是对象的地址。
-
这两种对象访问方式各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。使用直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销。
java栈是针对每一个线程的,每一个线程都会有自己的栈,维护在其内部的引用就是本地变量表。
在java中每一个reference只是指向了一个内存块,其中并没有实例对象的内容,因此可能会出现这种情况:同一个线程多个引用只想了同一个内存地址,不同线程的引用指向了同一个内存地址。
因此当gc进行内存清理时,若将在java堆中的对象进行了移动,那么对于基于指针的对象定位方式就需要将他内部的全部引用进行更新,更新次数较多。但是基于句柄的更新方式则不同,由于全部对象都指向了一个句柄,而句柄中维护了一个指向对象的指针,因此在进行内存整理时,只需要更新句柄中实例的内容就可以了。
当进行对象访问时,基于指针的对象定位方式可以直接获取到对象的内容,但是基于句柄的需要两步才能获取到对象内容,时间上有所损失。