JVM的四种垃圾回收算法(标记清除,标记整理,复制,分代回收)

  • Post author:
  • Post category:其他




JVM中的四种垃圾回收算法


垃圾回收算法只有四种:


1、标记清除算法

2、标记整理算法

3、复制算法

4、分代回收算法


注意:这四种都是基于可达性分析算法来判断是否为垃圾的。



第一、标记清除算法

在这里插入图片描述


步骤



1、先找到GC roots根来遍历将非垃圾对象进行标记。

2、他会将垃圾进行清除,就是图中的情况。


注意

:jvm并不是真正的把垃圾对象进行了遍历,把内部的数据都删除了,不是这样的,而是把垃圾对象的首地址和尾地址进行了保存,等到再次分配内存时,直接去地址列表中分配,所以清除的效率高。


优点

:清除速度快,效率高。


缺点

:会产生大量的内存碎片(就是很多不连续的内存空间),如果放入一个大的数组的时候,没有连续的内存放置大的数组,就会出现内存溢出,但是所有的内存碎片加起来可以放置一个大的对象,所有说内存使用率低,造成内存不连续。



第二、标记整理算法

在这里插入图片描述


步骤



1、先找到GC roots根来遍历将非垃圾对象进行标记。

2、它会将垃圾进行清除,并且会将非垃圾对象进行向前移动,使得内存紧凑。


优点

:不会出现内存碎片,提高了内存的利用率


缺点

:清除速度慢,因为在整理期间会有对象的拷贝和移动,并且引用内存的对象的地址要进行改变。



第三、复制算法

在这里插入图片描述


注意:左边是from区,右边是to区


步骤



1、先找到GC roots根来遍历将非垃圾对象进行标记。

2、然后将from区的非垃圾对象进行复制,到to区,并且进行整理,整理完成之后会将from区的数据进行清空,然后交换from和to区,使得from区一直是存储数据,to区一直空白的。


优点

:也不会出现内存碎片


缺点

:有效内存只有一半,只有一半存储数据,太浪费空间



第四、分代回收算法

在这里插入图片描述

在这里插入图片描述


对象头有个参数为分代年龄


分代回收

分为新生代和老年代,

新生代分为伊甸园区和幸存区,幸存区分为from和to区

。一般情况下,新生代占1/3,老年代占2/3。然后伊甸园区占8/10,幸存区占2/10,from和to区各占1/2。


先来说说minor GC 和full GC


Minor GC

又称为新⽣生代GC : 指的是发生在新生代的垃圾收集。因为Java对象大多都具备朝生夕灭的特性,因此Minor GC(采⽤用复制算法)非常频繁,一般回收速度也比较快。


Full GC

又称为 老年代GC或者Major GC : 指发生在老年代的垃圾收集。出现了了Major GC, 经常会伴随至少一次的Minor GC(并非绝对,在Parallel Scavenge收集器器中就有直接进行Full GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。


先来说一下对象存储以及垃圾回收过程

放入对象时,对象先会来到伊甸园区,如果伊甸园的剩余内存大小可以放下,就直接放到伊甸园区,如果伊甸园内存不够,就会进行minor GC 将伊甸园区的对象进行回收,并且将存活的对象放置from区,将分代年龄进行加1。

新生代用的是复制算法



minor GC 回收时,会将伊甸园区的垃圾和幸存区的垃圾都会进行回收



如果对象来到伊甸园区,对象放不下,又到幸存区也放不下,就会进入老年代,然后放入老年代,一直这样,直到老年代放不下的时候**,先会进行一次minor gc ,如果进行完之后,还是内存不够,就会进行full GC** ,full GC 会将新生代和老年代都会进行回收,并且会使其他的进程全部停止,称为stop the word(STW),就是平常的卡顿,如果进行full GC 之后,内存还是不够的时候,就会抛出异常OOM。

老年代的算法是标记清除或者标记整理算法


注意

:minor GC 也会有STW现象,只是时间短暂,老年代进行STW的时候,时间较长,因为老年代占用的内存大,而且进行的标记清除或者标记整理,时间慢,所以一般情况尽可能的少进行full GC。


还有一个问题



什么时候对象进入老年代

1、对象的分代年龄到了15岁(默认情况下,可以自己设置)。

2、大对象直接进入老年代,就是大对象在新生代放不下,进行minor GC之后还是不够的情况下,会直接放入老年代。



版权声明:本文为lzh_99999原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。