JVM垃圾回收算法与垃圾收集器有哪些?

Jvm进行垃圾回收,首先需要判断对象是否存活,那么如何判断对象是否存活呢?
当垃圾收集器在对堆进行回收前,第一就是要确定哪些对象还在被引用,或者后面还需要被引用(即存活态),哪些是已经“死去”(即不可能再被任何途径使用),判断对象是否存活主要用两种算法,即引用计数算法和可达性分析算法。

判断对象是否存活以后,Jvm主要通过4种垃圾回收算法进行垃圾回收,主要是:标记清除算法、复制算法、标记整理算法和分代回收算法。关于以上6种算法,会单独以博客进行讲解。

JVM虚拟机中有七个垃圾收集器,如图(图中连线的意思是这些垃圾收集器之间可以配合使用):

1)Serial收集器(采用复制算法收集新生代垃圾)
Serial是串行的意思,也就是说它以串行的方式执行,它是单线程的收集器,只会使用一个线程进行垃圾收集工作,GC线程工作时,其它所有线程都将停止工作。

所以,Serial收集器==新生代单线程收集器,标记和清理都是单线程,优点是简单高效。在单个CPU环境下,由于没有线程交互的开销,所以拥有最高的单线程收集效率,所以,它是Client场景下的默认新生代收集器(是client级别默认的GC方式)。

2)ParNew收集器(采用复制算法收集新生代垃圾) 
可以认为是Serial收集器的多线程版本,但要注意一点,ParNew在单核环境下是不如Serial的,在多核的条件下才有优势。

Server场景下默认的新生代收集器,除了性能原因外,主要是因为除了Serial收集器,只有它能与CMS收集器配合使用。

3)Parallel Scavenge收集器(采用复制算法收集新生代垃圾)
并行收集器,追求高吞吐量,高效利用CPU。同样是多线程的收集器,其它收集器目标是尽可能缩短垃圾收集时用户线程的停顿时间,而它的目标是提高吞吐量,吞吐量一般为99%。

吞吐量=运行用户程序的时间/(运行用户程序的时间+垃圾收集的时间(GC线程时间))

停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验,所以高吞吐量适合对交互响应要求不高的场景,该收集器是server级别默认采用的GC方式,因为高吞吐量可以高效利用CPU时间,尽快完成程序的运算任务。

4)G1收集器(使用复制+标记整理算法收集新生代和老年代垃圾)
G1(Garbage-First的缩写)是一款面向服务端应用的垃圾收集器,在多CPU和大内存的场景下有很好的性能(使命是未来可以替换掉CMS收集器)。

G1把堆划分成多个大小相等的独立区域(Region),新生代和老年代不再物理隔离。

5)CMS收集器(采用标记清除算法收集老年代垃圾)
CMS(Concurrent Mark Sweep)收集器在JVM老年代收集器中占据重要地位,其最大特点在于垃圾回收线程几乎能做到与用户线程同时工作,它的工作流程主要有4个步骤:
初始标记:仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,需要停顿(Stop-the-world)

并发标记:进行GC Roots Tracing的过程,它在整个回收过程中耗时最长,不需要停顿

重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿(Stop-the-world)

并发清除:清理垃圾,不需要停顿

在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。但CMS收集器也有如下缺点:
吞吐量低
无法处理浮动垃圾
标记清除算法带来的内存空间碎片问题

6)Serial Old收集器(采用标记整理算法收集老年代垃圾)
与Serial收集器类似,不过Serial Old收集器只收集老年代,也是单线程收集器,是Client 场景下默认的老年代垃圾收集器

7)Parallel Old 收集器(采用标记整理算法收集老年代垃圾)
Parallel Scavenge收集器的老年代版本
在注重吞吐量的场景下,可以采用Parallel Scavenge + Parallel Old的组合

发布了224 篇原创文章 · 获赞 34 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_39309402/article/details/104770196