深入理解JVM------对象的内存布局

前言

上一篇复习了深入理解JVM------类加载器,我们知道了JVM如何装载一个类,那么JVM如何创建类的实例对象,以及对象如何分配内存,我们一起来复习下,本文中的虚拟机指的是HotSpot 虚拟机。

1、对象的内存布局

对象的内存布局不是JVM规范的一部分,属于实现的细节,Hotspot将对象分成3部分:对象头、实例数据、对齐填充。
深入理解JVM------对象的内存布局_第1张图片

2、对象的创建过程

虚拟机在解析class文件的时候,若遇到new指令,会先在常量池中查看是否有这个类的符号引用,如果没有需要进行类的加载过程。
类加载完成后,对象的大小便可确定,就可以为对象分配内存,有2种方式:

  • 指针提高(bump pointer),如果堆内存是规整的(说明采用的是“复制算法”或“标记整理法”), 那么只需要把指针移动一个对象大小的距离就完成了分配。
  • 空闲列表(free list), 如果堆内存是不连续的(说明采用的是标记-清除法,有碎片), JVM会维护一个可用内存队列, 从中查出足够大的可用内存分配给对象。

分配完内存后,为对象中的成员变量赋上初始值,设置对象头信息,调用对象的构造函数方法进行初始化,至此,整个对象的创建过程就完成了。

3、对象的访问方式

所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在栈中分配的。根据引用存放的地址类型的不同,对象有2种不同的访问方式。

  • 句柄访问方式
    深入理解JVM------对象的内存布局_第2张图片
    引用类型的变量存放的是该对象的句柄地址(reference),堆中有一块叫做“句柄池”的内存空间,句柄中包含了对象实例数据与类型数据各自的具体地址信息。

  • 直接指针(HotSpot采用)
    深入理解JVM------对象的内存布局_第3张图片
    引用类型的变量直接存放对象的地址,通过引用能够直接访问对象,但对象所在的内存空间需要额外的策略存储对象所属的类信息的地址。这种方式只需要一次寻址,所以在性能上要比句柄访问方式快。

结束语

根据HotSpot对象的访问方式,我们知道了对象在内存中的布局为什么需要对象头;根据GC算法,我们也清楚了对象分配内存的方式,本篇到此结束,希望大家都能有所收获。

你可能感兴趣的:(jvm,java,jvm)