Java 垃圾回收机制

垃圾回收(Garbage Collection,GC)

垃圾识别算法

在java中什么样的对象会被认定为垃圾呢?如何找到这些对象?

1.引用计数法

在java中,对象的使用时考引用来实现的。也就是说,如果一个对象没有被引用,这个对象就可能被认定为垃圾。
优点:实现简单,效率高
缺点:无法解决循环引用问题。

2.可达性分析

为了解决引用计算法的循环引用问题,java使用了可达性分析。在java中使用根搜索算法(GC Roots Tracing)判断一个对象是否是可达的。该方法的基本思想是通过一系列的“GC Roots”对象作为起点进行搜索,如果在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被判定为不可达的对象不一定就会成为可回收对象。被判定为不可达的对象要成为可回收对象必须至少经历两次标记过程,如果在这两次标记过程中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

垃圾回收算法

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

分为标记阶段和清除阶段。标记阶段标记出需要回收的对象,清除阶段清除这些对象,回收被这些对象占用的内存。
缺点:碎片化严重,可能会使一些大对象无法找到可利用的空间。

2.复制算法(Copying)

为了阶段标记清除算法的碎片化问题而提出的。将内存分为大小相等的两块,新建的对象都在其中一块内存中,当一块内存满后,将尚存货的对象复制到另外一块内存中,然后把已使用的内存清除掉。
优点:实现简单,内存效率高,不宜碎片化。
缺点:内存被压缩到原来的一半,如果存活的对象太多,复制效率就会很低。

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

结合以上两种算法,为了避免缺陷,提出的。标记阶段和标记清除算法相同,标记后不清除对象,而是将存活对象移向内存的另一端,然后清除端边界外的对象。

4. 分代收集算法(Generational Collection)

分代收集算法是目前用的最多的。将对象按照不同的生命周期划分不同的内存域。一半分为老生代(Tenured/Old Generation)和新生代(Young Generation)。
一般新创建的对象都放在新生代,而经过15次依旧没有被回收的对象,会进入老生代。
新生代,每次都有大量的对象需要被回收,所以用复制(Copying)算法,需要复制的少。
老生代,每次只有少量的对象需要被回收,所以用标记整理(Mark-Compact)算法。
新生代,将内存划分成一块较大的Eden空间和两块较小的Survivor(From Sapce,To Space)空间。每次使用Eden空间和一块Survivor空间。当进行回收时,将两块空间中还存活的对象复制到另外一块Survivor空间中。

垃圾收集器

垃圾收集算法是垃圾收集器的理论基础,而垃圾收集器就是其具体实现。

1.Serial/Serial Old

Serial/Serial Old收集器是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。

2.ParNew

ParNew收集器是Serial收集器的多线程版本,使用多个线程进行垃圾收集。

3.Parallel Scavenge

Parallel Scavenge收集器是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。

4.Parallel Old

Parallel Old是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。

5.CMS

CMS(Current Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

6.G1

G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型。

参考文章

Java垃圾回收机制与典型的垃圾回收算法
Java基础:JVM垃圾回收算法

原文地址:https://www.cnblogs.com/lick468/p/10677150.html