JVM学习记录—常见垃圾回收(GC)算法

目录

JVM内存分代模型

年轻代和老年代

确定是否回收

引用计数法

可达性算法

垃圾回收算法

复制算法(新生代回收算法)

标记清除算法

标记整理算法(老年代回收算法)

何时回收?

新生代

老年代


JVM内存分代模型

由上篇JVM内存模型中了解到,系统中创建的对象都是分配在堆上。堆的大小是固定的,那么如何利用好堆就是极为重要的。所以JVM分代模型为:年轻代、老年代和永久代(方法区)。

public class Method1{
    public static void main(String[] args) {
        Hello hello = new Hello();
    }
}
class Hello{
}

以上Java代码在JVM中具体的引用如下,首先是main方法进去虚拟机栈,然后hello方法进入虚拟机栈,hello这个局部变量又引用了堆中的Hello实例对象。那么一个庞大的系统,必然会创建各种各样的对象,那对象在堆中是如何存放的?

JVM学习记录—常见垃圾回收(GC)算法_第1张图片

年轻代和老年代

JVM将堆内存划分为了两个区域,即年轻代和老年代。年轻代主要存放的是创建和使用完即将被回收的对象,老年代存放的是一些长期被使用的对象。

年轻代同样是被划分为了几个区域,这里我将堆内存的大概分配策略和年轻代区域划分先说一下,后边具体说垃圾回收算法的时候大家就知道为什么这样划分了

JVM学习记录—常见垃圾回收(GC)算法_第2张图片

上图是堆内存分配策略

①如果对象躲过了一次Minor GC时候,它的年龄会增长一岁。默认情况下,当对象的年龄达到15岁的时候,就会被转移到老年代。这个配置在JVM参数“-XX:MaxTenuringThreshold”来设置

②有一个JVM参数,是“-XX:PretenureSizeThreshold”。这个参数的意思是当对象的大小大于设定的值的时候,就会直接把对象分配在老年代中


JVM学习记录—常见垃圾回收(GC)算法_第3张图片

上图是1.8以前的JVM堆区域的具体划分

这里与1.8后的不同之处就在于永久代被元数据替代。需要注意的是这里新生代被划分为了三个区域 ①Eden区②Survivor1区③Survivor2区,这三个区域所占的大小比例为8:1:1,具体下文再解释。

确定是否回收

引用计数法

在 Java 中,引用与对象相关联,如果要操作对象,则必须使用引用。因此,可以通过引用计数来确定对象是否可以回收。实现原则是,如果一个对象被引用一次,计数器 +1,反之亦然。当计数器为 0 时,该对象不被引用,则该对象被视为垃圾,并且可以被 GC 回收利用。

可达性算法

对每个对象,分析下有谁在引用它,然后一层一层向上判断,看是否有一个GC Roots。例如局部变量就可以作为GC Roots,如果被局部变量引用,那么就不能被回收。

垃圾回收算法

常见的垃圾回收算法有标记清除法、标记整理算法和复制算法。而现而今大部分JVM都是采用分代手机算法,即按照新生代和老年代的特点采用合适的回收算法。

复制算法(新生代回收算法)

复制算法主要运用在新生代中,把新生代内存划分为两块内存区域,然后只使用其中一块,待那块内存快满的时候,就把里面的存活对象一次性转移到另外一块内存区域,然后回收原来那块的垃圾对象。

JVM学习记录—常见垃圾回收(GC)算法_第4张图片

整个垃圾回收的流程就是,刚开始创建的对象都是在Eden区域的,如果Eden区域快满了,就会触发垃圾回收。Eden区把存活的对象都转移到空着的S1区域,接着Eden区就会被请客。然后再次分配对象到Eden区中直到满了进行下一次垃圾回收,这时会将S1中存活的对象和Eden区存活的对象转移到空的Survivor区中(S2) 。这就是为什么新生代会被划分为8:1:1的结构了,这样对内存的利用率会大大提升。

标记清除算法

标记-清除算法采用从根集合(GC Roots)进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象,进行回收,如下图所示。标记-清除算法不需要进行对象的移动,只需对不存活的对象进行处理,在存活对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,因此会造成内存碎片。

JVM学习记录—常见垃圾回收(GC)算法_第5张图片

标记整理算法(老年代回收算法)

 

标记-整理算法采用标记-清除算法一样的方式进行对象的标记,但在清除时不同,在回收不存活的对象占用的空间后,会将所有的存活对象往左端空闲空间移动,并更新对应的指针。标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,因此成本更高,但是却解决了内存碎片的问题。具体流程见下图:

JVM学习记录—常见垃圾回收(GC)算法_第6张图片

何时回收?

新生代

新生代垃圾回收又叫Minor GC,当Eden区域满的时候,就会触发Minor GC

老年代

老年代垃圾回收又叫Full GC。

  • Minor GC前,会判断之前进入老年代的对象平均大小,发现大于,就会触发Full GC。
  • Minor GC后,剩余的存活对象的大小大于Survivor区域的大小,也大于了老年代可用内存的大小,就会触发Full GC。

你可能感兴趣的:(JAVA)