为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程,所以不适合服务器环境。
堆内存中新生代垃圾回收器(Serial):
串行收集器是最古老,最稳定以及效率高的收集器,只使用一个线程去回收,但其在进项垃圾收集过程中可能会产生较长的停顿(Stop-The-World)状态。虽然在收集垃圾的过程找那个需要暂停所有其他的工作线程,但是它简单高效,对于限定单个CPU环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器依然是java虚拟机运行在Client模式下默认的新生代垃圾收集器。
堆内存中老年代垃圾回收器(Serial Old):
Serial old是Serial垃圾收集器老年代版本,它同样是单线程的收集器,使用标记-整理算法,这个收集器也主要是运行在Client默认的老年代垃圾收集器,在老年代中,也充当CMS收集器的后备垃圾收集方案。(GC单线程)
多个垃圾回收器并行工作,此时用户线程是暂时的,适用于科学计算/大数据处理等弱交互场景。
堆内存中新生代垃圾回收器(ParNew、Parallel Scavenge):
ParNew收集器其实就是Serial收集器新生代的并行多线程版本,最常见的应用场景是配合老年代CMS GC工作,其余的行为和Serial收集器完全一样,ParNew垃圾收集器在垃圾收集过程中同样也要暂停所有其他的工作线程。(GC多线程)
JVM配置:-XX:+UseParNewGC 使用ParNew收集器
Parallel Scavenge收集器类似ParNew也是一个新生代垃圾收集器,使用复制算法,也是一个并行的多线程的垃圾收集器,俗称吞吐量优先收集器。(GC多线程)
JVM配置:-XX:+UseParallelGC 使用Parallel Scavenge收集器
堆内存中老年代垃圾回收器(Parallel Old):
Parallel Old收集器是Parallel Scavenge的老年代版本,使用多线程的标记-整理算法,Parallel Old收集器在JDK1.6才开始提供。
在JDK1.6之前,新生代使用Parallel Scavenge收集器只能搭配老年代的Serial Old收集器,只能保证新生代的吞吐量优先,无法保证整体吞吐量。
JDK1.8后考虑新生代Parallel Scavenge和老年代Parallel Old收集器的搭配策略。
JVM配置:-XX:+UseParallelOldGC 使用Parallel Old收集器
CMS(Concurrent Mark Sweep:并发标记清除) 是一种以获取最短回收停顿时间为目标的收集器。
CMS非常适合堆内存大、CPU核数多的服务器端应用,也是G1出现之前大型应用的首选收集器。
用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程,互联网公司多用它,适用对响应时间有要求的场景。 主要在老年代回收。
初始标记(Initial Mark):只是标记一下GC Roots能关联的对象,速度很快,仍然需要暂停所有工作线程。
并发标记(Concurrent Mark):进项GC Roots跟踪过程,和用户线程一起执行,不需要暂停工作线程,主要标记过程、标记全部对象。
重新标记(Remark):为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有用户线程。
并发清除(Concurrent Sweep):清除GC Roots不可达对象,和用户线程一起工作,不需要暂停工作线程,基于标记结果,直接清除对象。
CMS优点:并发收集停顿低。缺点:并发执行对CPU资源消耗大,标记清除算法会产生碎片。
JVM配置:-XX:+UseConcMarkSweepGC 使用CMS收集器
G1(Garbage-First)垃圾回收器将堆内存分割成不同的区域,然后并发的对其进行垃圾回收。G1收集器的设计目标是取代CMS收集器,它同CMS相比,不会产生大量内存碎片,并可以添加预测机制,用户可以指定期望停顿时间(可通过配置-XX:MaxGCPauseMills=n最大停顿时间)。
区域化内存划分Region,整体变为一系列不连续的内存区域,避免了全内存区的GC操作。核心思想是将整个堆内存区域分成大小相同的子区域(Region),在JVM启动时会自动设置这些子区域的大小,在堆的使用上,G1并不要求对象的存储一定在物理上连续的,只要逻辑上连续即可,每个分区也不会固定的为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数配置-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区。
大小范围在1MB~32MB,最多能设置2048个大小相同的子区域,也即能够支持的最大内存为:32MB*2048 = 65536MB ≈ 64G内存
收集演示:
这些Region的一部分包含新生代,新生代的垃圾收集依然采用暂停所有应用线程的方式,将存活的对象拷贝到老年代或者Survivor空间。
这些Region的一部分包含老年代,G1收集器通过将对象从一个区域复制到另一个区域,完成了清理工作。这就意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样就不会有CMS的内存碎片问题了。
JVM配置:-XX:+UseG1GC 使用G1收集器
组合选择:
-XX:+UseSerialGC
-XX:+UseParallelGC或者
-XX:+UseParallelOldGC
-XX:+UseConcMarkSweepGC
-XX:+ParNewGC