垃圾收集器入门

1. GC的由来

C语言是如何清理内存的?

C语言本身是没有提供GC能力的,是程序员通过malloc来获取堆内存,通过free函数来释放内存。

那么让我想想,垃圾回收的执行逻辑跟业务操作是没有关系的。让我联想到“让程序员专注于业务开发“这句话,大师们应该会将垃圾回收这块工作给封装起来,下沉到高级语言的功能包中,于是Java,c++,c#…此类高级语言自带gc功能应运而生。

2. GC的步骤

关于GC,主要有以下步骤

第一步:哪些对象需要回收?
第二步:如何回收?

接下来,我围绕这2个步骤分析,垃圾收集的过程。

2.1 哪些对象需要回收

如果让我来实现这个功能,那么我会怎么做?先标记哪些对象没有被引用了,接着就是回收它。

Jdk标记垃圾对象的方法主要有2种:

  • 引用计数法(废弃,存在循环引用问题)
  • 可达性分析法(至今仍然在使用)

这里有2个关键点,面试的时候可能会被问到,

  1. 引用计数法的循环引用问题是什么?
  2. 可达性分析法,GC ROOT有哪些?

2.2 如何回收

JDK是如何回收上述的“垃圾对象”,我们需要考虑以下几个问题:

  • 什么时候回收的?
  • 使用什么算法回收的?
2.2.1 什么时候回收

我推理,应该有如下二种方式:

  • 被动触发
    比例法:对象引用失效的时候,触发GC,触发的条件是当前堆中,空闲内存占据总内存的一定比例,则启动GC。

  • 定时触发

    定时清理法,启动守护线程去定期执行GC,触发条件同上。

2.2.2 使用什么算法回收的

如何判断垃圾回收算法是最好的呢?我理解需要满足以下条件:

  • 1⃣️垃圾清理速度快
  • 2⃣️清理后,堆内存的碎片少,近乎没有内存碎片
  • 3⃣️垃圾清理的回收线程不影响用户线程(低延迟)
  • 4⃣️垃圾清理消耗的资源少,包含cpu和垃圾收集器本身的内存消耗。(高吞吐量)

我们搞清楚垃圾回收的目标,再看jdk提供的垃圾收集的算法方案,可能会比较好理解点。

标记-清除算法

最简单的,标记完垃圾对象后,直接清除,如下图
在这里插入图片描述

缺点,从图中可以看出,容易产生内存碎片,不满足2⃣️。

标记-整理算法

解决了标记-清除算法的“内存碎片问题”,在GC后,移动存活对象,整理出连续空闲内存块,如下图

在这里插入图片描述

缺点,从上述描述中可知,移动存活对象,会引发对象内存地址的变更,存在用户线程与GC回收线程并发访问对象的地址变化冲突问题,JDK提供的解决方案是STW,即暂停用户线程,那么就不满足3⃣️的条件了。

标记-复制算法

也解决了标记-清除算法的“内存碎片问题”,核心思想是将其中内存块(S0),进行垃圾对象的标记,再将存活的对象复制到另一片空白内存中(S0),最后直接清除到S0的整块内存,近似压缩整理碎片空间了。如下图
在这里插入图片描述

缺点,从上述描述中可知,多占用了一块空白堆内存S1,不满足4⃣️

3. GC的实现产品

太晚了,改天待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值