美文网首页
新生/老年/永久代

新生/老年/永久代

作者: BeYearn | 来源:发表于2018-12-18 16:52 被阅读0次

    当代主流虚拟机(Hotspot VM)的垃圾回收都采用“分代回收”的算法。“分代回收”是基于这样一个事实:对象的生命周期不同,所以针对不同生命周期的对象可以采取不同的回收方式,以便提高回收效率。
    Hotspot VM将内存划分为不同的物理区,就是“分代”思想的体现。如图所示,JVM内存主要由新生代、老年代、永久代构成。

    图片.png

    一. 新生代(Young Generation)
    大多数对象在新生代中被创建,其中很多对象的生命周期很短。每次新生代的垃圾回收(又称Minor GC)后只有少量对象存活,所以选用复制算法,只需要少量的复制成本就可以完成回收。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。

    新生代内又分三个区:一个Eden区,两个Survivor区(一般而言. 一个from, 一个to),大部分对象在Eden区中生成。MinorGC时,先把Eden和ServivorFrom区域中还存活的对象复制到ServicorTo区域(如果有对象的年龄可晋升,则赋值到老年代区. 如果ServicorTo不够了,会发生promotion, 就放到老年区,即分配担保机制)。然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区.

    对象每经历一次Minor GC,年龄加1,达到“晋升年龄阈值”后,被放到老年代,这个过程也称为“晋升”, 显然,“晋升年龄阈值”的大小直接影响着对象在新生代中的停留时间,在Serial和ParNew GC两种回收器中,“晋升年龄阈值”通过参数MaxTenuringThreshold设定,默认值为15.

    二. 老年代(Old Generation)
    在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代,该区域中对象存活率高。老年代的垃圾回收(又称Major GC)通常使用“标记-清理”或“标记-整理”算法。整堆包括新生代和老年代的垃圾回收称为Full GC(HotSpot VM里,除了CMS之外,其它能收集老年代的GC都会同时收集整个GC堆,包括新生代)。
    当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。

    三. 永久代(Perm Generation)
    主要存放元数据,例如Class、Method和Meta(元数据),与垃圾回收要回收的Java对象关系不大。相对于新生代和年老代来说,该区域的划分对垃圾回收影响比较小.
    它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

    在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。
    元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制.

    采用元空间而不用永久代的几点原因:(参考:http://www.cnblogs.com/paddix/p/5309550.html
    1、为了解决永久代的OOM问题,元数据和class对象存在永久代中,容易出现性能问题和内存溢出。
    2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出(因为堆空间有限,此消彼长)。
    3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低
    4、Oracle 可能会将HotSpot 与 JRockit 合二为一。

    相关文章

      网友评论

          本文标题:新生/老年/永久代

          本文链接:https://www.haomeiwen.com/subject/ypplkqtx.html