在介绍垃圾收集器之前,首先介绍以下这几个概念
1. Stop-the-world
它是指 JVM 由于要执行 GC 而停止了应用程序的执行,并且这种情形会在任何一种 GC 算法中发生。当 Stop-the-world 发生时,除了 GC 的线程以外,其他的线程均处于等待的状态,直到 GC 任务完成。
实际上,很多 GC 优化都是通过减少 Stop-the-world 的时间来提高程序的性能。
2. Safe-point
程序执行时并非在所有地方都能停顿下来开始 GC,只有在某些特定的位置才可以,这些特定的位置被称为安全点(Safe-point)。在使用 GC roots 分析可达性时,引用关系不会发生改变的点就是安全点,常用的安全点有如下几种:
- 方法调用
- 循环跳转
- 异常跳转
3. JVM 运行模式
JVM 运行模式有如下这两种:
- Client:启动快,进入稳定期后运行速度不如 Server 快。
- Server:启动慢,进入稳定期后运行速度优于 Client . Server 模式采用的是重量级的虚拟机,对程序会进行更多的优化。
垃圾收集器
-
Serial 收集器(新生代)
Serial 即串行的意思,也就是说它以串行的方式执行,它是单线程的收集器,只会使用一个线程进行垃圾收集工作,GC 线程工作时,其它所有线程都将停止工作。
使用复制算法收集新生代垃圾。
它的优点是简单高效,在单个 CPU 环境下,由于没有线程交互的开销,因此拥有最高的单线程收集效率,所以,它是 Client 场景下的默认新生代收集器。
显式的使用该垃圾收集器作为新生代垃圾收集器的方式:-XX:+UseSerialGC -
ParNew 收集器(新生代)
就是 Serial 收集器的多线程版本,但要注意一点,ParNew 在单核环境下是不如 Serial 的,在多核的条件下才有优势。
使用复制算法收集新生代垃圾。
Server 场景下默认的新生代收集器,除了性能原因外,主要是因为除了 Serial 收集器,只有它能与 CMS 收集器配合使用。
显式的使用该垃圾收集器作为新生代垃圾收集器的方式:-XX:+UseParNewGC -
Parallel Scavenge 收集器(新生代)
同样是多线程的收集器,其它收集器目标是尽可能缩短垃圾收集时用户线程的停顿时间,而它的目标是提高吞吐量(吞吐量 = 运行用户程序的时间 / (运行用户程序的时间 + 垃圾收集的时间))。
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。
使用复制算法收集新生代垃圾。
显式的使用该垃圾收集器作为新生代垃圾收集器的方式:-XX:+UseParallelGC -
Serial Old 收集器(老年代)
Serial 收集器的老年代版本,Client 场景下默认的老年代垃圾收集器。
使用标记-整理算法收集老年代垃圾。
显式的使用该垃圾收集器作为老年代垃圾收集器的方式:-XX:+UseSerialOldGC -
Parallel Old 收集器(老年代)
Parallel Scavenge 收集器的老年代版本。
在注重吞吐量的场景下,可以采用 Parallel Scavenge + Parallel Old 的组合。
使用标记-整理算法收集老年代垃圾。
显式的使用该垃圾收集器作为老年代垃圾收集器的方式:-XX:+UseParallelOldGC -
CMS 收集器(老年代)
CMS(Concurrent Mark Sweep),收集器几乎占据着 JVM 老年代收集器的半壁江山,它划时代的意义就在于垃圾回收线程几乎能做到与用户线程同时工作。
使用标记-清除算法收集老年代垃圾。
工作流程主要有如下 4 个步骤:
初始标记: 仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿(Stop-the-world)并发标记: 进行 GC Roots Tracing 的过程,它在整个回收过程中耗时最长,不需要停顿重新标记: 为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿(Stop-the-world)并发清除: 清理垃圾,不需要停顿
在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。
但 CMS 收集器也有如下缺点:
吞吐量低无法处理浮动垃圾标记 - 清除算法带来的内存空间碎片问题
显式的使用该垃圾收集器作为老年代垃圾收集器的方式:-XX:+UseConcMarkSweepGC -
G1 收集器(新生代 + 老年代)
G1(Garbage-First),它是一款面向服务端应用的垃圾收集器,在多 CPU 和大内存的场景下有很好的性能。HotSpot 开发团队赋予它的使命是未来可以替换掉 CMS 收集器。
使用复制 + 标记 - 整理算法收集新生代和老年代垃圾。
G1 把堆划分成多个大小相等的独立区域(Region),新生代和老年代不再物理隔离。
显式的使用该垃圾收集器作为老年代垃圾收集器的方式:-XX:+UseG1GC