Java 垃圾回收算法概述

一、概述

Java的GC,垃圾回收机制。

目前常用的标记算法有两种,主要是为了对垃圾进行标记,为之后进行垃圾回收做准备:

1:引用计算算法;

2:可达性分析算法;

目前常用的垃圾回收算法有三种:

1:标记-清除算法;

2:标记-整理算法;

3:复制算法;

目前使用的GC:【jdk1.8版本已经没有永久代了】

1:MinorGC方式(主要用于年轻代,具体点的是Eden区满时触发GC。)

2:  FullGC方式(收集整个Java堆和方法区的垃圾收集。)

3:  Major GC (针对 老年代的垃圾收集。 目前,只有CMS收集器会有单独收集老年代的行为)

4: Mixed GC (收集整个新生代以及部分老年代的垃圾收集。 目前只有G1收集器会有这种行为。)

模型概述,将堆内存分为年轻代和老年代,年轻代占1/3,老年代占2/3 ;

其中年轻代一个Eden区,两个Survivor区  【Eden :S : S 为  8:1:1 ;】

Java 垃圾回收算法概述_第1张图片

二、java垃圾回收-标记算法

java在进行内存回收的时候需要判断当前对象是否为垃圾,才能进行回收。

对象被判定为垃圾的标准:没有被其他对象引用;

判定对象是否为垃圾的算法:引用计数算法;可达性分析算法;

    1:引用计算算法:通过对象实例的引用计数器是否为0来决定对象实例能否被当做垃圾收集,被引用+1,完成引用-1,0收集。

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

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

    2:可达性分析算法:判断对象的引用链是否可达来决定对象是否可以被回收

    具体:从GCRoot出发,对内存中的整个内存图进行遍历,不断标记存活对象,最后将不可达的回收

三、java垃圾回收-回收算法

标记-清除算法:先标记(可达性算法),在清除,会产生大量不连续内存碎片。

标记-整理算法:先标记(可达性算法),在清除,再整理,避免碎片内存产生,使用于存活率搞的场景(老年代)

复制算法:当对象面空间不够时,会将对象面存活对象复制到空闲面,并将对象面所有对象内存清除。解决产生碎片内存问题,顺序分配内存,简单高效,适用于对象存活率低的场景(适用年轻代,据统计每次回收只有10%对象存活)

分代收集算法:按对象声明周期不同划分区域并才采用不同算法,提高jvm回收效率。年轻代存活率低使用复制算法,老年代对象存活率高使用标记-清楚/标记-整理算法。

四、JAVA常用的两种GC方式

    GC分类:MinorGC方式(主要用于年轻代)、FullGC方式(主要用于老年代)

    1:MinorGC方式(年轻代1/3堆空间,E:S:S默认8:1:1),

    年轻代:尽可能快速收集掉生命周期短的对象,Eden区,两个Survivor区(from区to区),一次MinorGC,活着对象年龄加1,默认15岁进入老年代(--XX:MaxTenuringThreshold 设置新生代最大年龄)

     年轻代垃圾回收过程概述:

     1:每次年轻代的Eden区满了之后,会进行一次MinorGC,清理Eden区,此时将Eden存活对象【 假设存在对象A 】复制到from区,之后Eden清空,此时存活对象年龄为1。如图:

初始Eden区域满了,A的年龄为0

Java 垃圾回收算法概述_第2张图片

 进行一次MinorGC,A的年龄为1

Java 垃圾回收算法概述_第3张图片

     2:   Eden再次满了之后,再次进行一次MinorGC,将Eden存活的对象【 假设存在对象B 】复制到to区。同时将form区的对象A 复制到 to 区,并将Eden、from区清空。此时对象A的年龄为2,对象B的年龄为1。如图:

        Eden区满,此时A的年龄为1,B的年龄为0Java 垃圾回收算法概述_第4张图片

  进行一次MinorGC,A的年龄为2,B的年龄为1

Java 垃圾回收算法概述_第5张图片

     3:Eden再次满了之后,再次进行一次MinorGC,将Eden存活的对象 以及 to 区的存活对象复制到from区,将Eden、to区清空。此时对象A的年龄为3,对象B的年龄为2。如图:

      Eden区满, 此时A的年龄为2,B的年龄为1Java 垃圾回收算法概述_第6张图片

   进行一次MinorGC,A的年龄为3,B的年龄为2

Java 垃圾回收算法概述_第7张图片

注意,默认超过15岁进入老年代。进入了Survivor区的对象失效也会被清除。

2  FullGC方式(老年代2/3堆空间)

老年代:存放生命周期较长的对象; FullGC比MinorGC慢,但执行频率低。

    触发FullGC条件:

  • 老年代空间不足;

  • 永久代空间不足(jdk7及以前版本);

  • CMS GC出现fail;

  • MinorGC晋升到老年代的平均大小大于老年代的剩余空间;

  • 调用System.gc();

  • 使用RMI进行RPC或管理的jdk应用,每小时会执行1此FullGC

你可能感兴趣的:(JVM,java,经验分享)