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

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

[[438235]]

本文转载自微信公众号「程序员巴士」,作者七十一 。转载本文请联系程序员巴士公众号。

前言

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

回家等通知

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

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

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

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

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

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

阿巴阿巴:

标记清楚算法

标记整理算法

复制算法

分代收集算法

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

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

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

阿巴阿巴: 好的。

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

当场拿Offer

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

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

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

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

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

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

阿巴阿巴: 循环引用的对象外部引用断开的情况。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

阿巴阿巴: 标记整理算法孕育而生,解决了过多内存碎片的问题。

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

阿巴阿巴: 复制算法实现简单、方便且效率很高,也不需要考虑内存碎片的问题,但是要将内存缩小为原来的一半,这代价无疑很高。

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

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

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

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

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

总结

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

 

责任编辑:武晓燕 来源: 程序员巴士
相关推荐

2021-12-25 22:31:10

MarkWord面试synchronize

2021-11-08 09:18:01

CAS面试场景

2021-12-16 18:38:13

面试Synchronize

2021-02-03 15:30:10

面试垃圾回收器前端

2020-12-10 08:43:17

垃圾回收JVM

2024-03-25 11:03:38

Vue修饰符lazy

2022-01-05 08:56:20

Vue修饰符面试

2020-02-03 17:22:34

垃圾回收原理种类

2023-08-02 08:48:11

C#碟片算法

2018-05-10 15:48:47

面试面试官Java

2024-07-26 08:47:07

2022-03-21 11:33:11

JVM垃圾回收器垃圾回收算法

2020-07-28 00:58:20

IP地址子网TCP

2021-05-11 21:56:11

算法清除JVM

2010-08-23 15:06:52

发问

2021-01-06 05:36:25

拉链表数仓数据

2017-08-04 10:53:30

回收算法JVM垃圾回收器

2022-01-20 10:34:49

JVM垃圾回收算法

2023-02-20 08:08:48

限流算法计数器算法令牌桶算法

2022-01-05 09:55:26

asynawait前端
点赞
收藏

51CTO技术栈公众号