当前位置:首页 > 问答 > 正文

其实就是想让大家能比较轻松地理解JVM里面那些复杂的垃圾回收机制,别太枯燥但又不能太简单,能稍微抓住重点讲清楚原理和应用吧

JVM的垃圾回收(Garbage Collection, GC)就是这个房间的“保洁团队”,他们的核心工作就两步:找到垃圾,然后收走垃圾,听起来简单吧?但难点在于,这个房间特别大,程序猿们还在不停地制造新垃圾,而且保洁团队打扫的时候,还不能影响程序猿们正常工作(或者影响越小越好),这就衍生出了各种有趣的打扫策略。

第一步:怎么确定哪个咖啡杯是垃圾?

保洁团队很聪明,他们不是看哪个杯子脏了,而是用了一个“人缘测试法”,他们规定:凡是还有程序猿正在使用或者能通过某种方式联系到的物件,就不是垃圾,反之,如果一个物件放在角落里,所有程序猿都表示“那玩意儿跟我没关系了”,那它就是垃圾。

技术上,这叫做可达性分析,想象房间中央有个“总经理”(叫做GC Roots),所有直接为总经理服务的物件(比如总经理的电脑),以及被这些物件引用的其他物件(比如电脑连接着的打印机),都属于“可达”的,要留着,而那些从总经理出发,无论通过多少层关系都联系不上的物件,就被标记为垃圾,这个方法非常精准,能避免误扔了谁正在用的“传家宝”。

第二步:知道了垃圾在哪,怎么收?

收垃圾也有不同的套路,对应着不同的保洁团队工作模式,这也是GC算法复杂和有趣的地方。

清洁工大妈模式(标记-清除) 这是最基础的方式,保洁大妈先在整个房间里转一圈,把所有垃圾都贴上纸条(标记),然后第二次再转一圈,把贴了纸条的垃圾直接扔进垃圾桶(清除)。

  • 优点:简单直接。
  • 缺点:会产生内存碎片,想象一下,扔掉了几个散落在各处的咖啡杯,房间空出了很多小空隙,但都不连续,这时候如果程序猿想搬一张大沙发(一个大对象)进来,虽然总的空闲空间够,但没有一块完整的空地能放下,这就尴尬了。

整理收纳师模式(标记-整理) 为了解决碎片问题,更高级的整理收纳师来了,他们也是先标记垃圾,但清理方式不同:他们不是直接扔掉垃圾,而是把还有用的物件都规整到一起,紧紧地排列在房间的一侧,然后直接把另一侧整个区域清空。

  • 优点:完全没有碎片,空间整齐划一,分配新物件非常快。
  • 缺点:搬动所有有用物件是个大工程,比较耗时。

复制搬运工模式(复制算法) 这个模式更绝,他们把房间一分为二,命名为A区和B区,平时只让程序猿在A区活动,当A区快满的时候,保洁团队就出动,把A区里所有还有用的物件一个个搬到全新的B区,而且搬的时候就在B区紧密排列好,搬完之后,直接把整个A区一次性清空,接下来程序猿就在B区活动,如此反复。

  • 优点:超级高效,没有碎片,分配速度极快。
  • 缺点:太奢侈了!永远有一半的房间是空着的,空间利用率只有50%。

现实中的应用:分代收集思想

JVM的设计者发现,程序里大部分物件其实都挺“短命”的,比如方法里临时创建的变量,可能方法执行完就没用了,只有少数物件(比如全局配置)会活得很久。

于是他们想出了一个绝妙的主意:把房间(堆内存)分成不同的“区域”来管理,这就是分代收集

  • 伊甸园(Eden区):所有新来的物件都先放在这里,这里就像公司门口的快递堆放点,非常热闹,但绝大多数包装盒(对象)在拆开后很快就会被扔掉,这里是垃圾产生的重灾区。
  • 幸存者区(Survivor区):通常有两个,比如S0和S1,经历过伊甸园垃圾回收后还能存活下来的“幸运儿”物件,会被移动到幸存者区,它们会在这里接受多次考验,每次回收都活下来的,才算得上是“老员工”。
  • 养老区(Old/Tenured区):在幸存者区经历了多次回收(默认15次)依然坚挺的对象,会被晋升到这里,这里的物件都是“老资格”了,很少会“死掉”,所以打扫的频率很低。

基于这种分代设计,JVM采用了组合拳式的保洁策略:

  • 伊甸园和幸存者区(合称为年轻代),因为垃圾多、存活少,采用效率极高的复制算法(就像复制搬运工),因为存活对象少,复制起来的成本很低,所以年轻代的回收(称为Minor GC)非常频繁,但速度也极快,对程序影响很小。
  • 养老区(称为老年代),因为里面的物件存活率高,再使用复制算法就不划算了(要复制的东西太多),所以一般采用标记-清除标记-整理算法(就像清洁工大妈或整理收纳师),老年代的回收(称为Major GCFull GC)速度较慢,停顿时间会较长,是我们要尽量避免的。

所以你看,JVM的垃圾回收并不是一个死板的机制,而是一套非常智能的、基于对象生命周期特征的动态管理系统,它通过“分而治之”的策略,用最小的代价完成了房间的保洁工作,让程序猿们可以安心地创造和丢弃,而不用担心被垃圾淹没,理解了这个比喻,你也就抓住了JVM垃圾回收的精髓。

其实就是想让大家能比较轻松地理解JVM里面那些复杂的垃圾回收机制,别太枯燥但又不能太简单,能稍微抓住重点讲清楚原理和应用吧