java堆内存简单剖析

434 阅读1分钟

 作为java内存模型中最核心的一个组件:堆  ,它在jvm hotspot虚拟机中充当什么样的角色,存储什么数据,如何分类,如何回收。这里笔者为了好理解,做一个简单的介绍。

1、堆存储的数据

            堆作为jvm最核心的组件,没有之一,存储的主要的数据就是------对象。任何函数中创建的任何对象,我们几乎都可以在堆中找到实例。当然部分对象可能存在源空间也即是方法区中。

2、堆内存怎么分类

            主要分为年轻代 和老年代。其中年轻代又可分为eden(伊甸园),和两个幸存者(Survivor1,Survivor2)。老年代是一个非常大的内存空间,存储着堆内存中绝大部分的对象。具体的模型如下:

  

3、堆内存如何回收。

          堆内存回收策略在java虚拟机中有多种,主要可以分为3中,标记整理,引用计数,复制回收

          当我们创建对象的时候,首先jvm会更具创建对象的大小来判断对象到底会存放到那个堆空间中,如果对象过于庞大,超出了年轻代的可连续内存空间,那么jvm会自动将对象放置到老年代中,并对年轻代进行gc清理,因为老年代是非常大的。当然一般情况下,会放置到年轻代的伊甸园中。

          年轻代的内存清理方式: 当伊甸园中的连续内存空间不足以放置对象时,就会执行gc清理(这里的gc清理使用引用计数+标记整理),如果清除后,还有剩下的对象被线程引用,则将剩下的对象采用复制算法复制到其中一个幸存者中,然后将伊甸园中的所有对象清除。  之后到下一次清理伊甸园时,会将伊甸园连带着其中一个有对象的幸存者区域一起清理,将最后剩下的对象复制到另一个幸存者区域,将伊甸园以及被复制的幸存者区域对象全部删除。以此迭代,当来回gc清理15次后,如果幸存者还有对象数据,则将这部分对象移动到老年代区域。

          而老年代区域,也会在内存空间不足时进行空间gc清理,当gc清理也无法保证老年代有可用内存时,就会抛出堆内存溢出的异常。