• 新生代垃圾回收


    之前的两篇文章(java执行时数据区浅析、java垃圾收集器(GC)浅析)介绍了java执行时数据区以及GC垃圾回收算法的相关知识,大家能够先去看看这两篇文章。
    本篇文章将重点关注新生代的垃圾回收。

    大部分JVM都会採用所谓的分代收集方式去回收垃圾,什么是分代收集呢?
    依据对象的存活周期的不同将内存划分为好几块。通常是把java堆分为新生代和老年代,这样就能够依据各个年代的特点採用最适合的收集算法。新生代中,每次垃圾收集时都发现大批对象死去,仅仅有少量存活,那就选用复制算法。老年代由于对象存活率高,没有额外空间对它进行分配担保,那就必须使用“标记-清理”或者“标记-整理”等重量级算法来进行回收。

    单纯从JVM的功能考虑,并不须要新生代,全然能够针对整个堆进行操作。新生代存在的唯一理由是优化垃圾回收的性能。更详细的说,把堆划分为新生代和老年代有两个优点:
    1.简化了新对象的分配(仅仅在新生代分配内存);
    2.能够更有效的清除不再须要的对象(即死对象,新生代和老年代使用不同的回收算法)。

    通过广泛研究面向对象实现的应用,发现一些特点:
    1.大部分对象的生存时间都非常短;
    2.新生对象非常少引用生存时间长的对象。
    所以,新生代通过复制算法能够高效的回收垃圾。

    依据上面的思想,我们继续将堆区域划分成例如以下部分:

    首先堆能够划分为新生代和老年代,然后新生代又能够划分为一个Elden区和两个Survivor(幸存)区。
    依照规定,新对象会首先分配在Eden中(假设对象过大,比方大数组,将会直接放到老年代)。在GC中,Eden中的对象会被移动到survivor中,直至对象满足一定的年纪(定义为熬过minor GC的次数),会被移动到老年代。

    新生代採取复制算法,在Minor GC之前,to survivor区域保持清空,对象保存在Eden和from survivor区,minor GC执行时,Eden中的幸存对象会被拷贝到to Survivor(同一时候对象年龄会添加1)。而from survivor区中的幸存对象会考虑对象年龄,假设年龄没达到阈值,对象依旧拷贝到to survivor中。假设对象达到阈值那么将被移到老年代。复制阶段完毕后,Eden和From幸存区中仅仅保存死对象,能够视为清空。假设在复制过程中to幸存区被填满了,剩余的对象将被放到老年代。最后,From survivor和to survivor会调换一下名字,下次Minor GC时,To survivor变为From Survivor。

    步骤例如以下图所看到的:

    总结一下,对象一般出生在Eden区,年轻代GC过程中,对象在2个幸存区之间移动,假设对象活到适当的年龄,会被移到老年代。当对象在老年代中死亡时,就须要更高级别的GC,更重量级的GC算法。

    调优的重要性:新生代的大小设置非常重要,假设新生代过小,会导致新生对象非常快就晋升到老年代中,在老年代中对象非常难被回收。假设新生代过大,会发生过多的复制过程。因而我们须要找到一个合适的大小,不幸的是,要想获得一个合适的大小,仅仅能通过不断的測试调优,这就须要JVM參数了。


  • 相关阅读:
    (精华)将json数组和对象转换成List和Map(小龙哥和牛徳鹤的对话)
    优先队列底层实现是堆(heap)(操作系统进程调度)
    (透彻理解)最精锐代码::堆的三种基本操作新建-插入-删除
    (考研)读者写者问题(附代码)
    (考研)黑电吃苹果同步互斥问题(附代码)
    (考研)哲学家进餐问题(附代码)
    (考研)吸烟者问题(赋代码)
    (考研)PV操作和信号量
    01.第一章_C++ Primer学习笔记_开始
    C++学习笔记
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4259194.html
Copyright © 2020-2023  润新知