• GC垃圾回收


    1. 垃圾回收之标记算法

    • 可达性分析算法

      1. 通过判断对象的引用链是否可达来决定对象是否可以被回收

      2. 可作为GC Root的对象

        • 虚拟机栈中引用的对象(栈帧中的本地变量表)

        • 方法区中常量引用的对象

        • 方法区中的静态属性引用的对象

        • 本地方法栈中JNI(Native方法)的引用对象

        • 活跃线程的引用对象

    • 引用计数算法

      • 优点:执行效率高,程序执行受影响较小

      • 缺点:无法检测出循环引用的情况,导致内存泄漏

    2. 垃圾回收之回收算法

    • 标记-清除算法

      从根集合进行扫描,对存活的对象进行标记;对堆内存从头到尾进行线性遍历,回收不可达对象内存

      缺点:产生大量不连续的碎片化内存

    • 复制算法

      分为对象面和空闲面,对象在对象面上创建,存活的对象被从对象面复制到空闲面,最后将对象面所有对象内存清除

      优点:解决了碎片化问题,顺序分配内存,简单高效,适用于对象存活率低的场景(新生代适用)

    • 标记-整理算法

      从根集合进行扫描,对存活的对象进行标记;移动所有存活的对象,且按照内存地址依次排列,然后将末端内存地址以后的内存全部回收

      优点:避免内存的不连续性,不用设置两块内存互换,适用于存活率高的场景(老年代适用)

    • 分代收集算法

      按照对象生命周期的不同划分区域以采用不同的垃圾回收算法(垃圾回收算法的组合拳)

    3. GC的分类

    • Minor GC

      新生代:尽可能快速收集掉那些生命周期短的对象,采用复制算法,包括Eden区和2个Survivor区,即S0区和S1区,其比例为8:1:1,新生代和老年代的比例是1:2

      image-20210526174325652

      • 对象如何晋级到老年代

        1. 新生代每经过一次Minor GC垃圾回收后,其存活的对象的年龄就增加1岁,默认达到15岁后该对象就会进入到老年代,也可以通过调整参数-XX:MaxTenuringThreshold来设置进入老年代的阈值。

        2. 经过多次的Minor GC后Survivor区中存放不下的对象

        3. 一个对象所占的内存超过了Eden区和Survivor区,该对象会直接晋级到老年代,可以通过参数-XX:PretenuerSizeThreshold设置最大对象的内存,超过该值就会直接进入老年代

      • 常用调优参数

        • -XX:SurvivorRatio Eden和Survivor的比值,默认是8,也就是Eden占新生代的8/10

        • -XX:NewRatio 老年代和新生代内存的大小的比例

        • -XX:MaxTenuringThreshold 对象从新生代晋升到老年代经过GC次数的最大阈值

    • Full GC

      老年代:生命周期存活较长的对象,一般采用标记-清除算法和标记-整理算法,一般使用Full GC,执行Full GC的同时也伴随着对新生代的垃圾回收

      Full GC 比Minor GC慢,但执行频率低

      • 触发Full GC的条件

        1. 老年代空间不足,一个在Eden区存放不下的大对象,会直接放到老年代,如果老年代也存放不下,就会触发Full GC

        2. 永久代空间不足(只针对KJDK7.0之前版本)

        3. CMS GC时出现promotion failed,concurrent mode failure

        4. Minor GC晋升到老年代的平均大小大于老年代的剩余空间

        5. 调用System.gc()

        6. 使用RMI来进行RPC或管理JDK应用,每小时执行一次Full GC

    4. 常见的垃圾回收器

    1. 垃圾回收器之间的联系

      image-20210526184012384

      1.两个收集器之间有连线,表明它们可以搭配使用。

      2.其中Serial Old作为CMS出现"Concurrent Mode Failure"失败的后备预案。

      3.(红色虚线)由于维护和兼容性测试的成本,再JDK8时将Serial+CMS、ParNew+Serial Old这两个组合声明为废弃,并在JDK9完全取消了这些组合的支 持,即移除。

      4.(绿色虚线)JDK14中,弃用Parallel Scavenge+SerialOld组合。删除CMS垃圾回收器。

    2. 年轻代常见的垃圾回收器

      1. Serial 收集器: -XX:+UseSerialGC来开启S该 收集器,采用复制算法

        • 单线程收集,进行垃圾回收时,必须暂停所有工作线程

        • 简单高效,Client模式下默认的年轻代收集器

      2. ParNew收集器:-XX:+UseParNewGC来开启该收集器,采用复制算法

        • 多线程收集,其余的行为、特点和Serial收集器一样

        • 单核执行效率不如Serial,在多核下执行才有优势

      3. Parallel Scavenge收集器:-XX:+UseParallelGC来开启该收集器,采用复制算法

        • 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间),比如运行了100分钟,其中垃圾回收用了2分钟,则吞吐量=98%

        • 比起关注用户线程停顿时间(提升用户体验),更关注系统的吞吐量(适合在后台运算)

        • 在多核下执行才有优势,Server模式下默认的年轻代收集器

        • 对垃圾回收原理不太了解,以至于在优化过程中遇到问题时,可以在项目启动时设置参数-XX:+UseAdaptiveSizePolicy把内存调优交个JVM来完成

      4. 老年代常见的收集器

        1. Serial Old收集器:-XX:+UseSerialOldGC来开启该收集器,采用标记-整理算法

          • 单线程收集,垃圾收集时,必须暂停所有工作线程

          • 简单高效,Client模式下默认的老年代收集器

        2. Parallel Old收集器:-XX:+UseParallelOldGC来开启该收集器,采用标记-整理算法

          • 多线程,吞吐量优先

        3. CMS收集器:-XX:+UseConcMarkSweepGC,标记-清除算法

        4. G1收集器:-XX:+UseG1GC,复制+标记-整理算法(Garbage First)

          • 并发和并行

          • 分代收集

          • 空间整合

          • 可预测的停顿

          •  

       

     

     

  • 相关阅读:
    Spark算子--join
    Spark算子--filter
    Spark算子--reduceByKey
    Spark算子--mapPartitions和mapPartitionsWithIndex
    Spark算子--map和flatMap
    Flume环境搭建_五种案例
    枚举深入剖析
    Oracle_基本函数查询综合
    Oracle_复杂查询综合
    softmax 杂谈
  • 原文地址:https://www.cnblogs.com/seanRay/p/14814821.html
Copyright © 2020-2023  润新知