JVM垃圾回收机制

1、如何确定某个对象是垃圾

1)引用计数法:一个对象没有任何与之关联的引用。无法解决循环引用问题。

2)可达性分析:在“GC roots”和一个对象之间没有可达路径。不可达对象不等于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。

2、垃圾回收算法

1)标记-清除算法(Mark-Sweep)

最基础的垃圾回收算法,分为两个阶段:标注和清除。(内存碎片化)

                                       JVM垃圾回收机制 

2)复制算法(Copying)

将内存划分为等大小的两块,每次只使用其中一块,当这一块内存满后将存活的对象复制到另一块,把已使用的内存清掉。(不易产生碎片,但可用内存只有一半)

                                          JVM垃圾回收机制

3)标记-整理算法(Mark-Compact)

结合了以上两个算法,标记阶段和Mark-Sweep算法相同,标记后不是清理对象,而是将存活对象移向内存的一端,然后清除端边界外的对象。

                                         JVM垃圾回收机制

4)分代收集算法

  • 分代收集算法是目前大部分JVM采用的方法,核心思想是根据对象存活的不同生命周期将内存划分为不同的域。
  • 老生代:每次垃圾回收时只有少量对象需要被回收。
  • 新生代:每次垃圾回收时都有大量对象需要被回收。
  • 新生代一般采取Copying算法,因为大部分对象是需要回收的,即要复制的操作比较少。通常不是按照1:1划分新生代,一般将新生代划分为一块较大的Eden空间和两个较小的Survivor空间,每次使用Eden空间和其中一块Survivor空间,当进行回收时,将该两块空间中还存活的对象复制到另一块Survivor空间中。

                                         JVM垃圾回收机制

5)老生代一般采用Mark-Compact算法

6)方法区的永生代

3、垃圾收集器

1)Serial/Serial Old收集器:

最基本、最悠久的收集器。单线程,必须停止其他所有工作的线程。

2)ParNew收集器

是Serial多线程版本,其余行为与Serial完全一样。

3)Parallel Scavenge/Parallel Old(并行回收)收集器

  • 并行的多线程收集器,目标是达到可控的吞吐量(Throughput)。
  • 吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
  • 提供两个参数用于精确控制吞吐量,分别是控制最大垃圾收起停顿时间(-XX:MaxGCPauseMillis)参数、设置吞吐量大小(-XX:GCYimeRatio)参数。
  • 还有一个开关参数-XX:UseAdaptiveSizePolicy,如果打开就不需要手动指定新生代大小(-Xmn)、Eden与Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数,只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用MaxGVPauseMillis参数或GCTimeRation参数给虚拟机设立一个优化目标。

4)CMS收集器

一种以获取最短回收停顿时间为目标的收集器,基于“标记-清除”算法实现的,运作过程分为4个步骤:初始标记、并发标记、重新标记、并发清除。其中,初始标记、重新标记这两个步骤仍然需要“Stop The World”。

5)G1收集器

并行与并发、分代收集、空间整理(标记整理算法,复制算法)、可预测的停顿时间的收集器。运作可划分为:初始标记、并发标记、最终标记、筛选回收。