如何判断对象是否要回收?

对象回收的依据——是否被有效引用?

引用的可分为强引用(Strong Reference)——指向new 对象的引用、软引用(Soft Reference)——有用但没必要的引用、弱引用(Weak Reference)——没有必要的引用、虚引用(Phantom Reference)——为了在对象被回收时获得系统通知。

强引用只要存在就不回收;
软引用只有在内存即将不足的情况下才回收;
弱引用及虚引用随便回收。

怎么判断对象是否被有效引用?

  1. 引用计数法。如果对象的引用计数器为0,则表示该对象可以回收。但是存在互相引用无法清理的情况。

  2. 可达性分析法。通过创建一个成为“GC Root”的对象作为搜索根节点,向下搜索。如果对象到该对象之间没有引用链关联,则该对象可回收。

对象死亡的判决书

再对象确定没有引用的情况下,还需要判断其finalize方法没有被覆盖或者已经被执行一次(该方法只能执行一次),满足这两个条件,GC才会回收该对象。

如果finalize方法被覆盖,则将该对象加入一个 “F-Queue”队列中,由虚拟机创建的、优先级低的Finalizer的线程去处理。

如果对象在finalize方法中建立了与”GC Root”对象的连接链,则对象成功逃离了死亡的命运。否则,对象就被判决了死刑。

垃圾回收算法

标记-清理算法。

根据对象是否被有效引用进行标记,然后清理无用对象。
优点:简洁有效。
缺点:存在空间碎片,不利于下次对象内存的分配及内存空间的合理利用。

复制算法。

将内存划分为两大块,一块用于存储对象,另一块用于复制准备。第一步也是标记,第二步是把不需清理的对象复制到另一块内存区域,保持这些对象在内存空间上是连续排列。
优点:无碎片空间,且新对象内存空间分配便捷。
缺点:二分法对空间利用率不高,且复制过程中效率不高。由于新生代中无用对象多,需要复制移动的对象少,所以该法很适合。
改进版:内存划分为一块较大的Eden内存空间两块较小的Survivor空间(默认8:1:1),一块Eden及Survivor用于分配对象,另一块用于复制准备。如果要复制的对象的内存超出了准备的Survivor,则需要其他内存(老生代)进行分配担保。

标记-整理。

第一步标记。第二步将存活的对象都往前移动,在内存空间中紧密排列,然后对于边界外的内存空间进行清理。

分代收集算法。

将内存空间分为新生代老生代。新生代中每次垃圾回收时都会有大量对象死亡,需要复制的对象很少,因此采用复制算法。老生代对象的利用率高,存活时间长,因此采用标记-清理或者标记整理算法。

垃圾回收器

新生代垃圾收集器

1. Serial收集器

特点: Serial 收集器只能使用一条线程进行垃圾收集工作,并且在进行垃圾收集的时候,所有的工作线程都需要停止工作,等待垃圾收集线程完成以后,其他线程才可以继续工作。

使用算法:复制算法

2. ParNew收集器

特点: ParNew 垃圾收集器是Serial收集器的多线程版本。为了利用 CPU 多核多线程的优势,ParNew 收集器可以运行多个收集线程来进行垃圾收集工作。这样可以提高垃圾收集过程的效率。

使用算法:复制算法

3. Parallel Scavenge收集器

特点: Parallel Scavenge 收集器是一款多线程的垃圾收集器,但是它又和 ParNew 有很大的不同点。
Parallel Scavenge 收集器和其他收集器的关注点不同。其他收集器,比如 ParNew 和 CMS 这些收集器,它们主要关注的是如何缩短垃圾收集的时间。而 Parallel Scavenge 收集器关注的是如何控制系统运行的吞吐量。这里说的吞吐量,指的是 CPU 用于运行应用程序的时间和 CPU 总时间的占比,吞吐量 = 代码运行时间 / (代码运行时间 + 垃圾收集时间)。如果虚拟机运行的总的 CPU 时间是 100 分钟,而用于执行垃圾收集的时间为 1 分钟,那么吞吐量就是 99%。

使用算法:复制算法

老年代垃圾收集器

1. Serial Old收集器

特点: Serial Old 收集器是 Serial 收集器的老年代版本。这款收集器主要用于客户端应用程序中作为老年代的垃圾收集器,也可以作为服务端应用程序的垃圾收集器。

使用算法:标记-整理

2. Parallel Old收集器

特点: Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本这个收集器是在 JDK1.6 版本中出现的,所以在 JDK1.6 之前,新生代的 Parallel Scavenge 只能和 Serial Old 这款单线程的老年代收集器配合使用。Parallel Old 垃圾收集器和 Parallel Scavenge 收集器一样,也是一款关注吞吐量的垃圾收集器,和 Parallel Scavenge 收集器一起配合,可以实现对 Java 堆内存的吞吐量优先的垃圾收集策略。

使用算法:标记-整理

3. CMS收集器

特点: CMS 收集器是目前老年代收集器中比较优秀的垃圾收集器。CMS 是 Concurrent Mark Sweep,从名字可以看出,这是一款使用”标记-清除”算法的并发收集器。CMS 收集器的工作过程可以分为 4 个阶段:初始标记(CMS initial mark)阶段、并发标记(CMS concurrent mark)阶段、重新标记(CMS remark)阶段、并发清除((CMS concurrent sweep)阶段。

使用算法:复制+标记清除

3. G1 垃圾收集器

特点: 主要步骤:初始标记,并发标记,重新标记,复制清除。
使用算法:复制 + 标记整理

参考:

深入理解java虚拟机

JVM面试突破