java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java垃圾收集器

深入理解Java虚拟机之经典垃圾收集器

作者:崇尚学技术的科班人

这篇文章主要介绍了深入理解Java虚拟机之经典垃圾收集器的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

本文参考于《深入理解Java虚拟机》

1. 综述

1. 总述:

如果说收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者。《Java虚拟机规范》中对垃圾收集器应该如何实现并没有做出任何规定,因此不同的厂商、不同版本的虚拟机所包含的垃圾收集器都可能会有很大差别,不同的虚拟机一般也都会提供各种参数供用户根据自己的应用特点和要求组合出各个内存分代所使用的收集器。

2. 图示总述

在这里插入图片描述

上图展示了七种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用,图中收集器所处的区域,则表示它是属于新生代收集器抑或是老年代收集器

3. 应用中应如何做出选择?

虽然我们会对各个收集器进行比较,但并非为了挑选一个最好的收集器出来,虽然垃圾收集器的技术在不断进步,但直到现在还没有最好的收集器出现,更加不存在“万能”的收集器,所以我们选择的只是对具体应用最合适的收集器。这点不需要多加论述就能证明:如果有一种放之四海皆准、任何场景下都适用的完美收集器存在,HotSpot虚拟机完全没必要实现那么多种不同的收集器了。

2. Serial收集器

1. 简介

Serial收集器是最基础、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是HotSpot虚拟机新生代收集器的唯一选择。大家只看名字就能够猜到,这个收集器是一个单线程工作的收集器,但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作,更重要的是强调在它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束(“Stop The World”)。

2. 图解工作过程

在这里插入图片描述

3.使用的垃圾收集算法

标记-复制算法

4. 优点

简单而高效(与其他收集器的单线程相比),对于内存资源受限的环境,它是所有收集器里额外内存消耗最小的;对于单核处理器或处理器核心数较少的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率

5. 缺点

在垃圾回收过程中会触发 “Stop The World” 而产生停顿,从而导致用户体验不好。

6. 主要应用场景

Serial收集器对于运行在客户端模式下的虚拟机来说是一个很好的选择。

3. ParNew收集器

1. 简介

ParNew收集器实质上是Serial收集器的多线程并行版本(新生代收集器),除了同时使用多条线程进行垃圾收集之外,其余的行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法Stop The World对象分配规则回收策略等都与Serial收集器完全一致,在实现上这两种收集器也共用了相当多的代码。

2. 图解工作过程

在这里插入图片描述

3. 使用的垃圾收集算法

标记-复制算法

4. 补充概念

5. 主要应用场景

它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器(真正意义上的并发收集器,后面会介绍到)配合工作。

4. Parallel Scavenge收集器

1. 简介

Parallel Scavenge收集器也是一款新生代收集器,它同样是基于标记-复制算法实现的收集器,也是能够并行收集的多线程收集器。Parallel Scavenge的诸多特性从表面上看和ParNew非常相似。Parallel Scavenge收集器的特点是它的关注点与其他收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量

2. 补充概念

吞吐量就是处理器用于运行用户代码的时间与处理器总消耗时间的比值

在这里插入图片描述

如果虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。 停顿时间越短就越适合需要与用户交互或需要保证服务响应质量的程序,良好的响应速度能提升用户体验;而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务

3. 图解工作过程

在这里插入图片描述

4. 使用的垃圾收集算法

标记-复制算法

5. 相关的参数

Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的 -XX:MaxGCPauseMillis 参数以及直接设置吞吐量大小的 -XX:GCTimeRatio 参数。

5. Serial Old收集器

1. 简介

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法。

2. 图解工作过程

在这里插入图片描述

3. 使用的垃圾收集算法

标记-整理算法

4. 主要的应用场景

6. Parallel Old收集器

1. 简介

Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。

2. 图解工作过程

在这里插入图片描述

3. 使用的垃圾收集算法

标记-整理算法

4. 主要的应用场景

注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge 加 Parallel Old收集器这个组合。

7. CMS收集器

1. 简介

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。CMS收集器是基于标记-清除算法实现的。它非常适合在注重用户体验的应用上使用

2. 工作过程

3. 图解工作过程

在这里插入图片描述

4. 使用的垃圾收集算法

标记-清除算法

5. 优点

6. 缺点

7. 主要的应用场景

它非常适合在注重用户体验和要求停顿时间短的应用上使用

8. Garbage First收集器

1. 简介

G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。G1在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间,优先处理回收价值收益最大的那些Region。这种使用 Region划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。

2. 工作过程

从上述阶段的描述可以看出,G1收集器除了并发标记外,其余阶段也是要完全暂停用户线程的,换言之,它并非纯粹地追求低延迟,官方给它设定的目标是在延迟可控的情况下获得尽可能高的吞吐量,所以才能担当起“全功能收集器”的重任与期望。

3. 图解工作过程

在这里插入图片描述

4. 特点

5. 使用此收集器下的堆内存说明

在这里插入图片描述

G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。Region中还有一类特殊的Humongous区域(H),专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。每个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象将会被存放在N个连续的Humongous Region之中,G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待,如上图所示。虽然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它们都是一系列区域(不需要连续)的动态集合

6. 主要的应用场景

主要使用于服务端模式下的垃圾回收

到此这篇关于深入理解Java虚拟机之经典垃圾收集器的文章就介绍到这了,更多相关java垃圾收集器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文