JVM学习笔记之四:分代垃圾回收

原创
2014/02/12 17:59
阅读数 1.5K

    

    如图所示,在HotSpot虚拟机中共划分有三个代:年轻代(young generation),年老代(old generation)和持久代(permanent generation)。实际上真正有意义的是年轻代和年老代,对象的生成与消亡都发生在这两个区域。


    持久代(permanent generation)

    在开始介绍年轻代和年老代之前,先来说一说持久代吧。

    持久代的主要作用是存放java类等静态化的信息,可以看作是方法区的一部分。垃圾回收对持久代的影响并不大,只有某些需要动态生成类的应用才需要去关注这个区域的大小,可以通过-XX:MaxPermSize=<N>进行设置

    持久代是个比较神奇的概念,应该是Hotspot虚拟机里所特有的一个代。它是方法区的一部分,按常理不应该属于堆。并且在通过jvm参数设定各个区域大小的时候,可以很明显的发现持久代和堆的大小是需要分别指定的,两者不是一个整体。但是网络上铺天盖地的资料里都把它归属于堆,对此我一直感到无法理解,一种可能的解释是在早期的Hotspot虚拟机中,持久代就是堆的一部分。如果有高人清楚这么归类的原因,还望解惑。


    年轻代(young generation)

    年轻代是JVM堆中最常发生垃圾回收的区域,所有对象都生成于此。

    如上图所示,年轻代一般可以分成三个区域,其中一个是Eden区,另外的两个From和To都是Survivor区。一般新生成的对象都出现在Eden区,当Eden区被填满时,所有经过垃圾回收还存活的对象将被复制到两个Survivor区域中的一个,我们假定是From区(两个区域实际上没有任何区别,From和To只是为了更好的说明工作流程),当From区域也被填满时,这个区域经过垃圾回收仍存活的对象将会被复制进入To区域,原From区域被清空,并且从Eden区过来的数据将直接进入To区域。当To区域也被填满时,之前从From区域过来的那部分数据如果仍在活动,则将被放入年老代。

    需要注意的是,两个Survivor区域总有一个会是空的,并且Survivor是可以被设置为多个的。Survivor的个数越多,则对象在进入年老区之前要经历的垃圾回收次数也越多。


    年老代(old generation)

    在年轻代中经历多次垃圾回收后仍旧存活的对象,都将进入年老代。这个区域中的对象生命周期较长,当这个区域也被写满时,会触发整个堆的垃圾回收。


    堆的垃圾回收

    堆的垃圾回收一般被分成两种,分别是Scavenge GC 和 Full GC。

    Scavenge GC只发生在年轻代,当Eden区域的空间被写满时触发,触发后执行的动作就是发生在年轻代中的故事,不在复述。这种垃圾回收的目的就是尽快的为新生成的对象腾出空间,将生命周期较长的对象放入年老代。

    Full GC 对整个堆进行整理,当年老代或者持久代被写满时或者java程序中system.gc()被调用时会触发。Full gc的执行会引起程序的短时间暂停,因此如何合理有效的分配堆空间,减少Full gc的次数是JVM优化的一个重要内容。


展开阅读全文
打赏
1
14 收藏
分享
加载中
更多评论
打赏
0 评论
14 收藏
1
分享
返回顶部
顶部