JVM 知识梳理 (二) GC算法

一、前言

垃圾收集(Garbage Collection ),简称GC。是Java 的一种垃圾自动回收机制,但程序员可以手动执行 System.gc(),通知 GC 运行,但是 Java 语言规范并不保证 GC 一定会执行。

判定哪些对象需要被GC,主要有两种方法,引用计数法和可达性算法。

GC算法包括引用计数法、标记—清除、标记—压缩、复制算法。

二、判定哪些对象需要被GC

引用计数法Reference Count

引用计数法,也叫直接垃圾回收法,是老牌垃圾回收算法,当GC触发时,通过对象的引用来计算要不要回收。

给每个对象分配一个引用计数器,只要该对象被应用,计数器+1.取消引用就-1。

当GC触发时,如果该对象的引用计数器为零,那这个对象就是垃圾。

在这里插入图片描述
优点

即时回收,因为对象知道自己什么时候没用

缺点

引用和去除引用伴随着加法减法,影响性能。还有就是很难处理循环引用

需要注意的是,在主流虚拟机中,并未涉及引用计数法。

可达性算法(引用链法Tracing)

可达性算法,也叫间接垃圾回收算法。

该算法的思想是:从一个被称为 GC Roots 的对象开始向下搜索,找到活着的对象,活着得对象可以链接到,而如果一个对象到 GC Roots 没有任何引用链相连时,则说明此对象不可用。
在这里插入图片描述
Tracing法分为两部分:GC root和GC heap

那么GC root有哪些呢?

  1. java虚拟机栈中的引用的对象
  2. 方法区中的类静态属性引用的对象
  3. 方法区中的常量引用的对象,例如final User u = new User();
  4. 本地方法栈中的JNI(native方法)引用的对象

这些GC root会与GC heap中的对象进行相连。

三、GC算法

标记—清除

标记—清除算法是现代垃圾回收算法的思想基础

这个算法将垃圾回收分为了两个阶段,标记阶段和清除阶段

1.在标记阶段,首先通过根节点,标记所有从根节点开始可达对象,这时的可达对象代表还“有用”,而未标记的对象就是未被引用的垃圾对象。

2.在清除阶段,清除未被标记的垃圾对象。

在这里插入图片描述

优点

实现起来简单,不需要额外的空间

缺点

逐渐产生被细化的分块,不久后就会导致无数的 小分块散布在堆的各处,并且在分配对象的时候还得先遍历那些内存块可以用。

标记—压缩

标记-压缩算法适合用于存活对象较多的场合,如老年代

它在标记-清除算法的基础上做了一些优化,即在标记—清除算法后,将所有存活的对象压缩到内存的一端,然后清理这个边界外的所有空间
在这里插入图片描述
缺点:清除算法中,清除阶段也要搜索整个堆,不过搜索 1 次就够了。但 GC 标记 - 压缩算法要搜索 3 次,这样就要花费约 3 倍的时间,这是一个相当巨大的缺陷,特别是堆越大,所消耗的成本也就越大(看图)

优点:堆利用效率高。
而且 GC 标记 - 压缩算法不会出现 GC 复制算法那样只能利用半个堆的情况

复制算法

复制算法,在标记清除的的基础上改进而来的,适用于对象存活度低的场景,如年轻代

在这里插入图片描述
堆空间分配中,新生代:老年代 = 1:2

思想是将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。
需要注意的是,在复制算法下,两个survivor区(From和To区)同⼀时间会有⼀个满⼀个空,是交替的,并且空的总是To区。

值得知道的是,如果一次Young GC后存活的对象过多不能进入Survivor区,那么就直接进入老年代。

优点:
1、优秀的吞吐量: GC 标记 - 清除算法消耗的吞吐量是搜索活动对象(标记阶段)所花费的时间和搜索整体 堆(清除阶段)所花费的时间之和。
另一方面,因为 GC 复制算法只搜索并复制活动对象,所以跟一般的 GC 标记 - 清除算 法相比,它能在较短时间内完成 GC。也就是说,其吞吐量优秀。

2、高速分配:GC 复制算法不使用空闲链表。这是因为分块是一个连续的内存空间。比起 GC 标记 - 清除算法和引用计数法等使用空闲链表的分配,GC 复制算法明显快得多。

3、不会发生碎片化

缺点:
浪费内存空间,因为用这种算法,必须保证To区是空的。假如极端情况下对象100%存在,内存空间就会不够。所以在对象存存活度低时适合使用,我们知道年轻代是存活度低,所以事实上就是使用的复制算法。

总结

在这里插入图片描述
没有最好的算法,但有最合适的算法。

分代收集

现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。

在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,一般采用标记整理算法。

补充:HotSpot为什么要分为新生代和老年代?
  • 因为有的对象寿命长,有的对象寿命短。应该将寿命长的对象放在一个区,寿命短的对象放在一个区。
  • 不同的区采用不同的垃圾收集算法。寿命短的区清理频次高一点,寿命长的区清理频次低一点。提高效率。
参考

B栈狂神说JVM入门
JVM GC算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值