JVM

20-垃圾回收相关算法

2021-06-01  本文已影响0人  紫荆秋雪_文

一、标记阶段

1、垃圾标记阶段

二、标记阶段算法-引用计数算法(Reference Counting)

Java的GC测试

public class RefCountGC {
    // 5MB
    private byte[] bigSize = new byte[5 * 1024 * 1024];
    Object reference = null;

    public static void main(String[] args) {
        RefCountGC obj1 = new RefCountGC();
        RefCountGC obj2 = new RefCountGC();

        obj1.reference = obj2;
        obj2.reference = obj1;

        obj1 = null;
        obj2 = null;
    }
}
Heap
 PSYoungGen      total 38400K, used 13615K [0x0000000795580000, 0x0000000798000000, 0x00000007c0000000)
  eden space 33280K, 40% used [0x0000000795580000,0x00000007962cbc00,0x0000000797600000)
  from space 5120K, 0% used [0x0000000797b00000,0x0000000797b00000,0x0000000798000000)
  to   space 5120K, 0% used [0x0000000797600000,0x0000000797600000,0x0000000797b00000)
 ParOldGen       total 87552K, used 0K [0x0000000740000000, 0x0000000745580000, 0x0000000795580000)
  object space 87552K, 0% used [0x0000000740000000,0x0000000740000000,0x0000000745580000)
 Metaspace       used 2941K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 313K, capacity 392K, committed 512K, reserved 1048576K
public class RefCountGC {
    // 5MB
    private byte[] bigSize = new byte[5 * 1024 * 1024];
    Object reference = null;

    public static void main(String[] args) {
        RefCountGC obj1 = new RefCountGC();
        RefCountGC obj2 = new RefCountGC();

        obj1.reference = obj2;
        obj2.reference = obj1;

        obj1 = null;
        obj2 = null;

        // 显示垃圾回收
        System.gc();
    }
}
[GC (System.gc()) [PSYoungGen: 12949K->535K(38400K)] 12949K->543K(125952K), 0.0011575 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 535K->0K(38400K)] [ParOldGen: 8K->442K(87552K)] 543K->442K(125952K), [Metaspace: 2937K->2937K(1056768K)], 0.0249102 secs] [Times: user=0.01 sys=0.00, real=0.03 secs] 
Heap
 PSYoungGen      total 38400K, used 998K [0x0000000795580000, 0x0000000798000000, 0x00000007c0000000)
  eden space 33280K, 3% used [0x0000000795580000,0x0000000795679b20,0x0000000797600000)
  from space 5120K, 0% used [0x0000000797600000,0x0000000797600000,0x0000000797b00000)
  to   space 5120K, 0% used [0x0000000797b00000,0x0000000797b00000,0x0000000798000000)
 ParOldGen       total 87552K, used 442K [0x0000000740000000, 0x0000000745580000, 0x0000000795580000)
  object space 87552K, 0% used [0x0000000740000000,0x000000074006eaf8,0x0000000745580000)
 Metaspace       used 2943K, capacity 4556K, committed 4864K, reserved 1056768K
  class space    used 313K, capacity 392K, committed 512K, reserved 1048576K
Disconnected from the target VM, address: '127.0.0.1:61156', transport: 'socket'

小结

三、标记阶段算法-可达性分析算法(根搜索算法、追踪性垃圾收集)

1、GC Roots

所谓"GC Roots"根集合就是一组必须活跃的引用

2、GC Root 包含元素

四、Finalization 机制

判定一个对象 objA 是否可回收?

五、清除阶段

当成功区分出内存中存活对象和死亡对象后,GC 接下来的任务就是执行垃圾回收,释放掉无用对象所占用的内存空间,以便有足够的可用内存空间为新对象分配内存。目前在JVM中比较常见的三种垃圾收集算法有 标记-清除算法(Mark-Sweep)、复制算法(Copying)、标记-压缩算法(Mark-Compact)

1、标记-清除算法(Mark-Sweep)

标记-清除算法(Mark-Sweep)是一种非常基础和常见的垃圾收集算法,该算法被J.McCarthy等人在1960年提出并应用在Lisp语言

2、标记-复制算法

为了解决标记-清除算法在垃圾收集效率方面的缺陷,M.L.Minsky于1963年发表了著名的论文,“使用双存储区的Lisp语言垃圾收集器CA LISP Garbage Collector Algorithm Using Serial Secondary Storage”。M.L.Minsky 在该论文中描述的算法被人们称为复制(Copying)算法,它也被M.L.Minsky 本人成功地引入到了Lisp 语言的一个实现版本中

优点
缺点
适合场景

3、标记-压缩(整理)算法

优点
缺点

小结

小结.png

六、分代手机算法

前面所有这些算法中,并没有一种算法可以完全替代其他算法,它们都具有自己独特的优势和缺点。分代手机算法应运而生。

在HotSpot中,基于分代的概念,GC所使用的内存回收算法必须结合年轻代和老年代各自的特点

年轻代(Young Gen)
老年代(Tenured Gen)
分代收集算法应用

七、增量收集算法、分区算法

以上算法,在垃圾回收过程中,应用软件将处于一种 Stop The World 的状态。在 Stop The World 状态下,应用程序所有的线程都会挂起,暂停一切正常的工作,等待垃圾回收的完成。如果垃圾回收时间过长,应用程序会被挂起很久,将严重影响用户体验或者系统的稳定性。为了解决这个问题,即对实时垃圾收集算法的研究直接导致了增量收集(Incremental Collecting)算法的诞生

增量收集算法基本思想
上一篇 下一篇

猜你喜欢

热点阅读