跳至主要內容

JVM 垃圾回收


JVM 垃圾回收

在java语言中,垃圾回收GC的主要作用是回收程序中不再使用的内存。

垃圾回收算法

Java中常见的垃圾回收算法有标记清除算法、复制算法、标记整理算法、分代收集算法。

标记清除算法

标记清除算法是基础的垃圾回收算法,其过程分为标记和清除两个阶段。在标记阶段标记所有需要回收的对象,在清除阶段清除可回收的对象并释放其所占用的内存空间。

由于标记清除算法在清理对象所占用的内存空间后并没有重新整理可用的内存空间,因此如果内存中可被回收的小对象居多,则会引起内存碎片化的问题,继而引起大对象无法获得连续可用空间的问题。

复制算法

复制算法是为了解决清除标记算法内存碎片化的问题而设计的。复制算法首先将内存划分为两块大小相等的内存区域,即区域1和区域2,新生成的对象都被存放在区域1中,在区域1内的对象存储满后会对区域1进行一次标记,并将标记后仍然存活的对象全部复制到区域2中,这时区域1将不存在任何存活的对象,直接清理整个区域1的内存即可。

复制算法的内存清理效率高且易于实现,但由于同一时刻只有一个内存区域可用,即可用的内存空间被压缩到原来的一半,因此存在大量的内存浪费。同时,在系统中有大量长时间存活的对象时,这些对象将在内存区域1和内存区域2之间来回复制而影响系统的运行效率。

标记整理算法

标记整理算法结合了标记清除算法和复制算法的有点,其标记阶段和标记清除算法的标志阶段相同,在标记完成后将存活的对象转移到内存的另一端,然后清除该端的对象并释放内存。

分代收集算法

无论是标记清除算法、复制算法还是标记整理算法,都无法对所有类型的对象都进行垃圾回收。针对这些问题,分代收集算法针对不同的对象类型,JVM采用了不同的垃圾回收算法。

垃圾回收器

垃圾回收器的存在一方面把开发人员从释放内存的复杂工作中解脱出来,提高了开发人员的效率;另一方面,对开发人员屏蔽了释放内存的方法,可以避免因开发人员错误地操作内存而导致应用程序的崩溃,保证了程序的稳定性。

JVM针对新生代和老年代分别提供了多种不同的垃圾回收器,针对新生代提供的垃圾收集器有Serial、ParNew、Parallel Scavenge,针对老年代提供的垃圾收集器有Serial Old、Parallel Old、CMS,针对不同区域的Garbage First分区收集算法。

Serial垃圾回收器

Serial垃圾收集器基于复制算法实现。它是一个单线程收集器,当它正在进行垃圾收集时,必须暂停其他所有工作线程,直到垃圾收集结束。

ParNew垃圾回收器

ParNew垃圾收集器同样也是基于复制算法实现,不过它采用多线程模式工作。

Parallel Scavenge垃圾回收器

Parallel Scavenge垃圾收集器同样也是基于复制算法实现,也是采用多线程工作模式,不过在系统吞吐量上有很大的优化,可以更高效地利用CPU尽快完成垃圾回收任务。

CMS垃圾收集器

CMS(Concurrent Mark Sweep)基于标记清除算法实现,采用多线程工作模式。

CMS垃圾收集器是为老年代设计的垃圾收集器,其主要目的是达到最短的垃圾回收停顿时间,以便在多线程环境下以最短的垃圾收集停顿时间提高系统的稳定性。

Serial Old垃圾收集器

Serial Old垃圾收集器基于标记整理算法实现,采用单线程。

Parallel Old垃圾收集器

Parallel Old垃圾收集器基于标记整理算法实现,采用多线程。

Garbage First垃圾收集器

Garbage First垃圾收集器基于标记整理算法,采用多线程。

上次编辑于:
贡献者: Neil