JVM系列三(垃圾收集器).
一、概述
1. 哪些内存需要回收
上篇文章 我们介绍了 Java 内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟着回收了。
而方法区和 Java 堆是线程共享的,我们只有在程序处于运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。
2. 回收方法区
方法区的垃圾收集主要回收两部分内容:废弃常量和无用的类。
“废弃常量”指的是当前系统中没有任何一个对象引用指向该常量。
“无用的类”需要同时满足下面三个条件才有可能被虚拟机回收,至于最终是否回收还由虚拟机参数:-Xnoclassgc 控制。
- 该类的所有实例都已被回收,也就是 Java 堆中不存在该类的任何实例。
- 加载该类的 ClassLoader 已经被回收。
- 该类对应的 Class 对象没有被任何地方被引用,无法在任何地方通过反射访问该类的接口。
二、垃圾回收器
首先开始之前先看下 HotSpot 虚拟机所包含的收集器:

图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,则说明它们可以搭配使用。虚拟机所处的区域则表示它是属于新生代还是老年代收集器。
1. Serial 收集器
新生代收集器,复制算法收集,Serial 收集器是最基本、发展历史最悠久的收集器。它是一个单线程的收集器,只会使用一个 CPU 或一条收集线程去完成垃圾收集工作,它在垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

优点:简单高效;虚拟机 Client 模式下表现优异(Client 模式下内存较小、CPU较少,能减少许多线程交互的开销)。
缺点:回收工作需要 Stop The World ;单线程;不适用虚拟机 Server 模式(Server 模式下内存较大、CPU较多,导致回收工作停顿时间过长)。
2. ParNew 收集器
新生代收集器,复制算法收集,ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行回收外,其余行为包括控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与 Serial 收集器完全一样。

优点:多线程工作;可以与 CMS 收集器搭配工作;虚拟机 Server 模式下表现优异。
缺点:回收工作需要 Stop The World 。
3. Parallel Scavenge 收集器
新生代收集器,复制算法收集,多线程工作,Parallel Scavenge 收集器的关注点在于达到一个可控制的吞吐量(其他收集器的关注点是缩短垃圾收集时用户线程的停顿时间),停顿时间越短越适合需要与用户交互的程序;而高吞吐量则可以高效率的利用 CPU 时间,尽快完成程序的运行任务。
GC 自适应调节策略是 Parallel Scavenge 收集器和 ParNew 收集器的一个重要区别。它变现为:只需要把基本的内存数据设置好(如 -Xmx 设置最大堆),然后使用 MaxGCPauseMillis 参数(更关注最大停顿时间)或 GCRatio(更关注吞吐量)给虚拟机设立一个优化目标,那具体细节参数的调节工作就由虚拟机来完成了。
优点:多线程工作;注重系统吞吐量和CPU资源;自适应调节策略。
缺点:回收工作需要 Stop The World ;可选的老年代收集器过少,无法与 CMS 收集器配合工作,在 JDK1.5 之前只能和 Serial Old 收集器配合工作。
tips:
- 吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
- 自适应调节策略使用 -XX:+UseAdptiveSizePolicy 参数打开。
- 与吞吐量关系密切,故也称为“吞吐量优先”收集器。
4. Serial Old 收集器
老年代收集器,标记-整理算法,单线程,Serial Old 收集器是 Serial 收集器的老年代版本。
优点:虚拟机 Client 模式下表现尚可(Client 模式下内存较小、CPU较少,能减少许多线程交互的开销);CMS 收集器的后备预案(在并发收集Concurent Mode Failure时使用)。
缺点:回收工作需要 Stop The World ;单线程。
5. Parallel Old 收集器
老年代收集器,标记-整理算法,多线程,Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,在 JDK1.6 后开始提供。

优点:搭配 Parallel Scavenge 收集器使用,关注系统吞吐量以及CPU资源。
缺点:回收工作需要 Stop The World ;可搭配的新生代收集器仅有 Parallel Scavenge 收集器而已。
6. CMS 收集器
老年代收集器,标记-清除算法,多线程,CMS(Concurrent Mark Sweep)收集器是一种以获得最短回收停顿时间为目标的收集器,是真正意义上与用户线程并发运行的收集器,因此,使用 CMS 收集器能给用户带来良好的体验。

优点:并发收集;低停顿。
缺点:
- CMS 收集器对 CPU 资源敏感,在并发标记/清理 的时候,虽然不会导致用户线程停顿,但标记/清理工作是要占用一部分 CPU 资源的,这无疑会降低吞吐量。(CMS 默认启动的回收线程数是 (CPU 数量 + 3)/ 4)
- CMS 收集器无法处理浮动垃圾(Floating Garbage),可能出现 “Concurent Mode Failure” 失败而导致另一次 Full GC 的产生(使用 Serial Old 收集器)。浮动垃圾指的是并发清理阶段,用户线程并发运行产生的垃圾,当这些浮动垃圾的内存超过了CMS 运行期间预留的内存,就会导致 “Concurent Mode Failure” 失败。
- CMS 收集器使用的标记-清除算法会有大量的内存碎片出现,将会给大对象分配带来很多麻烦。
7. G1 收集器
分区(Region)收集器,标记-整理算法和复制算法,多线程,G1(Garbage-First)收集器在 JDK 7u4 版本发布,在 JDK9 中成为默认垃圾收集器,是一款面向服务端应用的垃圾收集器,它的目标也是获得最短停顿时间。

优点:
- 并行和并发,缩短 Stop The World 停顿的时间。
- 标记-整理算法、复制算法不会出现类似 CMS 的内存碎片问题。
- 可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不超过 N 毫秒。
推荐场景:
G1的首要目的是为那些需要大容量内存和较小 GC 延迟的应用程序提供解决方案。这通常是指那些堆大小设置在 6GB 以上,确定的、可以预测的暂停时间在 0.5 秒以内的应用程序。
如果应用程序符合以下一项或者多项特征,那么从 CMS 或者 ParallelOld 收集器切换到 G1 可能更合适。
- 活动对象占据了超过 50% 的 Java 堆空间。
- 对象分配率或者提升率波动明显。
- 不希望有长时间的垃圾收集暂停时间(超过0.5秒或1秒)。
参考链接:
- 《深入理解 JVM 虚拟机》
- G1垃圾收集器介绍
- jvm垃圾收集器(终结篇)
JVM系列三(垃圾收集器).的更多相关文章
- jvm系列 (二) ---垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...
- JVM笔记(三) 垃圾收集器(2)收集算法
垃圾收集器2:收集算法 主要通过阅读<深入了解Java虚拟机>(周志明 著)和网络资源汇集而成,为本人学习JVM的笔记.同时,本文理论基于JDK 1.7版本,暂不考虑 1.8和1.9 的新 ...
- JVM性能优化系列-(2) 垃圾收集器与内存分配策略
2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...
- JVM系列三:JVM参数设置
JVM系列三:JVM参数设置.分析 不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM.GC的参数,可以极大的减少由于GC工作,而导致的程序运 ...
- 【JVM】JVM中的垃圾收集器
垃圾收集器组合 Serial+Serial Old Serial+CMS ParNew+CMS ParNew+Serial Old Paralle Scavenge + Serial Old Para ...
- jvm系列(三):java GC算法 垃圾收集器
GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...
- jvm系列三、java GC算法 垃圾收集器
原文链接:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 ...
- jvm系列(三):GC算法 垃圾收集器
原文出处:纯洁的微笑 这篇文件将给大家介绍GC都有哪几种算法,以及JVM都有那些垃圾回收器,它们的工作原理. 概述 垃圾收集 Garbage Collection 通常被称为"GC" ...
- 深入理解JVM(三)垃圾收集器和内存分配策略
3.1 关于垃圾收集和内存分配 垃圾收集和内存分配主要针对的区域是Java虚拟机中的堆和方法区: 3.2 如何判断对象是否“存活”(存活判定算法) 垃圾收集器在回收对象前判断其是否“存活”的两个算法: ...
随机推荐
- shell中tar加密打包
tar 打包是一个很常见的操作,但是当打了一个包却又不想让别人看到里面的小秘密的时候就可以使用加密的方法进行打包. 以下是一个脚本实现的加密打包和解密的shell脚本: cat tar_passwor ...
- webpack优化之玩转代码分割和公共代码提取
前言 开发多页应用的时候,如果不对webpack打包进行优化,当某个模块被多个入口模块引用时,它就会被打包多次(在最终打包出来的某几个文件里,它们都会有一份相同的代码).当项目业务越来越复杂,打包出来 ...
- android逆向总结
首先项目里的java文件,以及项目引用到的第三方jar或aar包里面的class,统统都编译成classes.dex放在apk包的根目录,项目的资源目录和AndroidManifest.xml被处理生 ...
- 小白学习React官方文档看不懂怎么办?
最近在上React课程的时候,发现好多同学不会看文档,所以在这里写一篇文章,希望能给同学们一点点启发. 我们首先打开React官方网站——https://react.docschina.org/doc ...
- 🔥《手把手教你》系列基础篇之3-python+ selenium-驱动浏览器和元素定位大法(详细)
1. 简介 上一篇中,只是简单地一带而过的说了一些驱动浏览器,这一篇继续说说驱动浏览器,然后再说一说元素定位的方法. 完成环境的安装并测试之后,我们对Selenium有了一定的了解了,接下来我们继续驱 ...
- PHP中接口与抽象类的异同点有哪些
接口与抽象类的相同点: 1.抽象类和接口都有抽象方法 2.抽象类和接口不能创建实例对象 3.抽象类和接口使用意义相同(定义一种规范) 接口与抽象类的不同点: 1.接口中的方法必须全要是抽象方法(不能用 ...
- 第三个视频作品《小白快速入门greenplum》上线了
1.场景描述 第三个视频作品出炉了,<小白快速入门greenplum>上线了,有需要的朋友可以直接点击链接观看.(如需购买,请通过本文链接购买) 2. 课程内容 课程地址:https:// ...
- TensorFlow2.0极简安装(亲测有效)
x相信每一个学习深度学习的人来说都知道Google的深度学习框架TensorFlow,估计每个人都想成为一个TF Boy(TensorFlow Boy).我也是这个想法,于是我踏上了安装TensorF ...
- 题解 P1047 【校门外的树】
可以直接模拟,用珂朵莉树是不有点小题大做. 你怎么做珂朵莉都会骂你:"这么简单的模拟都要用***" 附赠珂朵莉照片一张 另外讲几点: 可以用int,你要不怕MLE #include ...
- JavaScript---1.计算机的编程基础
学习内容:编程语言.计算机基础 1编程语言 程序员通过编程语言来控制计算机 编程语言:机器语言(计算机只认识机器语言).汇编语言(直接对硬件操作,指令采用英文缩写的标识符,容易记忆).高级语言(C\C ...