C语言是如何清理内存的?
C语言本身是没有提供GC能力的,是程序员通过malloc来获取堆内存,通过free函数来释放内存。
那么让我想想,垃圾回收的执行逻辑跟业务操作是没有关系的。让我联想到“让程序员专注于业务开发“这句话,大师们应该会将垃圾回收这块工作给封装起来,下沉到高级语言的功能包中,于是Java,c++,c#...此类高级语言自带gc功能应运而生。
关于GC,主要有以下步骤
第一步:哪些对象需要回收?
第二步:如何回收?
接下来,我围绕这2个步骤分析,垃圾收集的过程。
如果让我来实现这个功能,那么我会怎么做?先标记哪些对象没有被引用了,接着就是回收它。
Jdk标记垃圾对象的方法主要有2种:
这里有2个关键点,面试的时候可能会被问到,
JDK是如何回收上述的“垃圾对象”,我们需要考虑以下几个问题:
我推理,应该有如下二种方式:
被动触发 比例法:对象引用失效的时候,触发GC,触发的条件是当前堆中,空闲内存占据总内存的一定比例,则启动GC。
定时触发
定时清理法,启动守护线程去定期执行GC,触发条件同上。
如何判断垃圾回收算法是最好的呢?我理解需要满足以下条件:
我们搞清楚垃圾回收的目标,再看jdk提供的垃圾收集的算法方案,可能会比较好理解点。
最简单的,标记完垃圾对象后,直接清除,如下图
缺点,从图中可以看出,容易产生内存碎片,不满足2⃣️。
解决了标记-清除算法的“内存碎片问题”,在GC后,移动存活对象,整理出连续空闲内存块,如下图
缺点,从上述描述中可知,移动存活对象,会引发对象内存地址的变更,存在用户线程与GC回收线程并发访问对象的地址变化冲突问题,JDK提供的解决方案是STW,即暂停用户线程,那么就不满足3⃣️的条件了。
也解决了标记-清除算法的“内存碎片问题”,核心思想是将其中内存块(S0),进行垃圾对象的标记,再将存活的对象复制到另一片空白内存中(S0),最后直接清除到S0的整块内存,近似压缩整理碎片空间了。如下图
缺点,从上述描述中可知,多占用了一块空白堆内存S1,不满足4⃣️
太晚了,改天待续...