我们知道在java中创建新对象的时候会产生一个引用类型和实例对象。
引用类型(reference):保存的是实例对象的引用,存储在栈中
实例对象:存储在堆中
注:新建实例对象的时候JVM同时会加载实例对象java类文件,将实例对象的类型信息保存在方法区中,后面我们可以看到访问对象的时候会同时去方法区中访问类型信息。
由于JVM规范中reference类型只定义了一个指向对象的引用,并没有定义引用如何去定位这个对象,因此不同的虚拟机有不同的方式去访问对象,主流的对象访问方式有两种:使用句柄和直接指针。
句柄方式
当使用句柄方式访问,java堆中会分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了实例对象数据和类型数据的两个具体地址信息,如下图:
直接指针方式
当使用直接指针方式访问,java堆对象的布局中就必须考虑如何存放访问对象类型数据的相关信息,因为reference中存储的就是对象地址,如下图。
总结
- 使用句柄的最大好处是 reference 中存储的是稳定的句柄地址,在对象移动(GC)是只改变实例数据指针地址,reference 自身不需要修改。
- 直接指针访问的最大好处是速度快,节省了一次指针定位的时间开销。
- 如果是对象频繁GC那么句柄方法好,如果是对象频繁访问则直接指针访问好。