面试官超级喜欢问的垃圾回收算法

# 前言

> 经过前段时间一面的通过,阿巴阿巴被邀请进入二面,这次她与遇到的面试官将继续为难她,要问她关于GC算法的问题

**回家等通知**

**面试官:** 你对JVM的垃圾回收了解吗?

**阿巴阿巴:** 嗯嗯,了解一些。

**面试官:** 那么JVM是如何判断一个对象是垃圾呢?

**阿巴阿巴:** 好像有一个可达性分析法。

**阿巴阿巴:** 就是对象可达会判定为活对象,然后不可达的就当作“垃圾”。

**面试官:** 嗯....讲一下你了解的垃圾回收算法吧。

**阿巴阿巴:**
>标记清楚算法
>
>标记整理算法
>
>复制算法
>
>分代收集算法

**面试官:** 嗯....那你对这些算法了解吗?

**阿巴阿巴:** 嗯....不太了解...

**面试官:** 行,今天先面到这里,你这边先回去等通知吧😈

**阿巴阿巴:** 好的。


>很遗憾,您未能通过面试,您的简历已加入公司人才库,期待下次相遇......
>


**当场拿Offer**


**面试官:** 你对JVM的垃圾回收了解吗?

**阿巴阿巴:** 嗯嗯,了解一些。

**面试官:** 那么JVM是如何判断一个对象是垃圾呢?

**阿巴阿巴:** 有两种方法,一种是引用计数法,另一种是可达性分析法。

**阿巴阿巴:** 引用计数法就是给对象一个引用计数器,每当有引用引向该对象时,引用计数器就加一,每当有引用断开的时候,引用计数器就减一,这样当引用计数起为零时,那么就认为这个对象已经没有用了,也就是所谓的垃圾,但是这种方式有个很大的弊端,对于循环引用无法处理。

**阿巴阿巴:** 循环引用的对象外部引用存在的情况,这种情况看似没啥问题,但是当我们把方法区的引用断开时,问题久暴露出来了。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuiwk0n5j31100negns.jpg)
**阿巴阿巴:** 循环引用的对象外部引用断开的情况。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuixoh8tj30z00nidhz.jpg)

**阿巴阿巴:** 上面这种引用断开的情况,显然对象A和对象B已经没有外部引用来引用它们,它们已经成为了垃圾,而引用计数器因为它们相互引用(循环引用),其值都为1,导致无法被回收,这个弊端导致引用计数法实际并没有在JVM中所使用。

**阿巴阿巴:** 可达性分析法就是通过GC Roots的对象,以它为根往下搜索,这条被搜索的路径称为“引用链”,当一个对象不被任何GC Roots的引用链所链接,那么久判定这个对象已经“死了”,我们一般称这个对象“不可达”。

**面试官:** 你刚有提到GC Roots,那你知道哪些对象可以作为GC Roots的对象吗?

**阿巴阿巴:** 嗯嗯了解,主要有以下四类对象可以作为GC Roots的对象。

> 虚拟机栈中引用的对象
>
> 方法区中静态属性引用的对象
>
> 方法区中常量引用的对象
>
> 本地方法栈中引用的对象

**阿巴阿巴:** 下面这张图可以直观的看出它们的关系。


![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuj0ldv8j30xq0u077c.jpg)

**阿巴阿巴:** 可以看出,只有被引用链链上的对象才能被判定为“存活”,而不在引用链上的对象则被判定为“死亡”,也将作为垃圾被回收。

**面试官:** 讲的很不错,那垃圾回收除了回收堆中的对象外,方法区中会有垃圾被回收吗?

**阿巴阿巴:** 方法区中也是有垃圾回收的,方法区中主要回收废弃了的常量和无用的类。

**面试官:** 嗯....讲一下你了解的垃圾回收算法吧。

**阿巴阿巴:** 垃圾回收算法主要有以下四类。

>标记清楚算法
>
>标记整理算法
>
>复制算法
>
>分代收集算法

**阿巴阿巴:** 标记清楚算法,是分为2个阶段的,第一个阶段进行“标记”,第二个阶段进行“清除”,先标记出所有要清除的对象,也就是灰色部分,然后进行回收。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuj2omw1j315g0doq3x.jpg)

**阿巴阿巴:** 采用标记清楚算法对堆进行垃圾清理后,产生了很多空间碎片,这些空间碎片使新对象的内存分配造成困难,不仅如此,标记清除算法在标记阶段和清除阶段的效率都不太高。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuj518e7j315y0cwjsb.jpg)

**阿巴阿巴:** 标记整理算法孕育而生,解决了过多内存碎片的问题。
![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyuj8frynj315q0cqt9i.jpg)


**阿巴阿巴:** 为了解决效率的问题,复制算法也出现了,即把一块内存分成大小相等的2块,每次使用的时候只使用其中的一块,当一块没存使用完的时候,把这块内存中存活的对象转移到另一块内存中,然后将这块内存中的对象全部清空。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyujbo5crj317k0h6abf.jpg)

**阿巴阿巴:** 复制算法实现简单、方便且效率很高,也不需要考虑内存碎片的问题,但是要将内存缩小为原来的一半,这代价无疑很高。
![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyujjolsuj31780hitaa.jpg)

**阿巴阿巴:** 而且新生代的对象大多数都是朝生夕死的,按照1:1的空间比例来使用复制算法,将极大的影响了内存的性能。

**阿巴阿巴:** 分代算法即将堆区进行划分,然后根据不同区域的情况来适用相应的垃圾回收算法。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwyujggygkj31li0noq5f.jpg)


**阿巴阿巴:** 下图是对新生代的细化,新生代分成Eden区和survivor区,其中survivor区又分为(s0和s1)俩个区域,它们的比例如图所示为8 : 1 : 1。新对象优先会在Eden区进行分配,标记清除算法在这里不适用,因为碎片太多,如果没有连续的足够空间来分配给对象,又会继续触发垃圾回收,对性能影响比较大。

![](https://tva1.sinaimg.cn/large/008i3skNgy1gwn9ma3yzmj30eg09nt93.jpg)

**阿巴阿巴:** 对于传统的GC来说,都无法避免GC过程中带来的“STOP-THE-WORLD”,我们一般简称STW,STW对系统性能的影响很大,那么如何消除STW或者减少STW的时间显得尤为重要,其实分代算法并非是一种具体的算法,和前面的标记清除、标记整理算法、复制算法不同的是,分代算法只是对对堆得一个划分,然后在不同区域使用不同的算法,从而将STW的时间细分到各个区域,使得STW时间不会持续很长一段时间,来达到提高系统性能的目的。

**面试官:** 讲的很清楚细致了,很不错,明天来上班吧😈。

# 总结
关于垃圾回收算法这一块,一定要答到GC Roots,以及各种垃圾回收算法,及他们的优点和缺点。

## ❤️/ 感谢支持 /
以上便是本次分享的全部内容,希望对你有所帮助^_^

喜欢的话别忘了 分享、点赞、收藏 三连哦~

欢迎关注公众号 **程序员巴士**,来自字节、虾皮、招银的三端兄弟,分享编程经验、技术干货与职业规划,助你少走弯路进大厂。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值