Java垃圾回收

概念

内存回收

因为语言的特性,Java不需要开发者手动回收内存,这部分工作由JVM来完成,至于何时回收需要回收的对象,从理论上来说最好的时机是在对象失去引用的时候,但是做到这一点对性能影响颇大,所有Java选择了另一种方法,那就是周期性去遍历所有对象,找出需要回收的对象然后做回收操作。

分代

正如上文所说,对象失去引用在回收线程发现它之前仍将存在一段时间,但是Java希望没用的对象能尽快被回收,比较简单的方式是提高回收线程的执行频率,但是这将导致性能问题,对象的生命周期内将被检查多次,生命周期长的对象将被无谓的多次被检查。为了权衡两者的关系,这才催生了另一个概念:分代,不同生命周期的对象分别放在不同的区域,不同区域的回收频率不同,这大大提高系统效率。

垃圾回收算法

  • 年轻代算法:标记复制。因为年轻代的垃圾回收频率高,年轻代的回收时间应该越短越好,所以年轻代以空间换时间,使用标记复制算法。
  • 年老代算法:标记整理、标记清除。因为年老代的对象都是在年轻代多次被回收后才来的,所以JVM就认为它们的生命周期长不可测,不应该频繁被无谓检查,所以年老代往往比较大,而且正常情况下长时间不应该被检查。

垃圾回收器

年轻代

年老代

组合方式

重点介绍CMS

CMS有何缺点?

  • 减小吞吐量
  • 造成浮动垃圾,增加了碎片问题负担

CMS模式下何时会触发FullGC?

  • Concurrent-mode-failure:空间问题;Promotion-mode-failure:碎片问题
  • 持久代满,且未启用 CMSClassUnloadingEnabled
  • 显式调用System.gc,且未启用ExplicitGCInvokesConcurrent