美文网首页
JVM调优2---垃圾回收算法及垃圾回收器

JVM调优2---垃圾回收算法及垃圾回收器

作者: 走在冷风中吧 | 来源:发表于2020-03-13 22:11 被阅读0次

    1. 常见的垃圾回收算法

    1.1 引用计数法

    历史最悠久的一种算法, 现在仍有语言使用。
    假设有对象A, 有任何一个对象对A进行引用, A的引用数+1, 如果对象A的引用为0, 则表示A没有被引用, 可以被回收。
    缺点: 无法解决循环引用的问题, 出现循环引用时垃圾回收无法回收两个对象。

    public class A{
     public B b;
    }
    public class B{
     public A a;
    }
    public class test{
       ... main (){
         A a = new A();
         B b = new B();
         a.b = b;
         b.a = a;
         a = null;
         b = null;
     }
    
    }
    

    以上 a,b 虽然都为null,但是因为存在循环引用,所以GC无法回收

    1.2 标记-清除算法

    标记: 从根节点开始标记引用的对象
    清除:未被标记引用的对象就是垃圾对象, 可以被清理

    GC未开始工作之前所有对象是未标记状态, 一旦发生内存空间耗尽,JVM将会终止应用程序的运行开启GC线程,然后根据根搜索算法开始标记工作。
    标记完成后将未被标记的对象进行清理, 清理完成将所有对象取消标记,JVM线程重新开始正常工作。

    缺点: 1. 效率较低, 标记和清除两个动作都需要循环遍历所有对象,且在GC执行时(标记清除)需要将jvm现有进程停掉, 影响性
    2. 标记清除算法整理出来的内存碎片化比较严重,回收的对象存在于内存的各个角落,所以清理出来的内存是不连贯的。

    1.3 标记-压缩算法

    在标记清除算法之上做了改进。 从根节点开始对对象的引用进行标记, 在清理阶段,将存活的对象压缩到内存的一段, 然后清理边界以外的垃圾, 从而解决了碎片化问题。
    缺点: 存在对象移动这个操作, 效率低
    优点: 解决了内存碎片化问题

    1.4 复制算法

    将原有内存空间一分为二, 每次只使用一半的内存, 当进行GC回收时, 将当前已使用空间存活的对象复制到另一半内存, 再将当前的内存一次性清除。

    缺点: 当内存中垃圾比较多, 存活对象较少时适用。 但是当存活对象较多时, 需要产生的复制则比较多, 则不适用。

    jvm年轻代内存空间

    使用复制算法实现垃圾回收机制
    JVM内存中, 年轻代分为 Eden区,Survior(from), Survior(to), 比例大小8:1:1
    1、GC开始之前,对象只会存在于Eden区和Survior(from)区中, to区是空的
    2、GC开始后, Eden区中存活的对象会被复制到to, 而from中对象存活的对象会根据他们的年龄至决定去向,达到一定范围就会移到老年区,没有的会移动到to区。
    3、经过这次GC, from区会被清空,这时候from和to的角色互换, 等待执行下一次GC任务。

    image.png
    1.5 分代算法

    现在大多是虚拟机采用这种算法, 根据对象的生命周期将堆内存分为年轻代和老年代。
    年轻代产生的垃圾较多, 存活对象较少,适用于复制算法。
    而老年代中的存活对象较多,垃圾较少,则适合于标记压缩算法或者标记清除算法。

    2. 垃圾收集器以及内存分配

    2.1 串行垃圾收集器

    单线程进行垃圾回收, 垃圾回收时只有一个线程在工作, java应用中的所有线程都需要暂停, 等待垃圾回收完成。对于交互性较强的应用,这种垃圾回收器是不能接受的。

    GC日志信息解读:

    • DefNew
      表示串行垃圾收集器
      4416k->512k(4928)
      4416表示gc前占有4416k大小, 512表示gc后占有512k内存,4928表示总大小。

    • FullGC
      表示内存空间全部(年轻代,老年代,Mataspace代)进行GC

    2.2 并行垃圾收集器

    在串行垃圾收集器的基础之上做了改进, 将单线程改为使用多线程进行垃圾回收,缩短了垃圾回收的时间。(这里是指并行能力较强的机器)
    当然, 并行垃圾收集器工作过程中也会暂停应用程序,只是并行速度更快些,暂停的时间也就更短。

    2.2.1 ParNew垃圾收集器

    ParNew垃圾收集器是运行在年轻代上的, 只是将串行的垃圾收集器编程了并行。
    -XX:+UserParNewGC 设置在年轻代上使用ParNew回收器, 老年代使用的依然是串行收集器。

    • ParNew
      表示并行垃圾收集器
    2.2.2 ParllelGC垃圾收集器

    和ParNewGC收集器一样, 在此基础上新增了两个和系统吞吐量相关的参数。

    • -XX:+UseParllelGC 新生代使用ParllelGC收集器
    • -XX:+UseParallelOldGC 老年代使用
    • -XX:+MaxGCPauseMillis=100 设置GC的最大停顿时间
    2.3 CMS垃圾收集器

    CMS全称Concurrent Mark Sweep, 是一款并发的,标记-清除算法的垃圾回收器, 该回收器,该回收器是针对老年代垃圾回收的, 通过参数: -XX:+UseConcMarkSweepGC进行设置。

    2.4 G1垃圾收集器

    G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器

    原理: G1垃圾收集器取消了物理上的分代,取之是将其划分成若干个区域, 这些区域在逻辑上分为老年代和年轻代区域。

    3. 可视化GC日志分析工具

    -XX:+PrintGCDetails可以对GC日志进行打印
    使用在线工具https://gceasy.io/分析
    Throughout:吞吐量, 吞吐量目标需要达到90%, 越高越好。

    相关文章

      网友评论

          本文标题:JVM调优2---垃圾回收算法及垃圾回收器

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