一、概述

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 收集器能给用户带来良好的体验。

优点:并发收集;低停顿。
缺点:

  1. CMS 收集器对 CPU 资源敏感,在并发标记/清理 的时候,虽然不会导致用户线程停顿,但标记/清理工作是要占用一部分 CPU 资源的,这无疑会降低吞吐量。(CMS 默认启动的回收线程数是 (CPU 数量 + 3)/ 4)
  2. CMS 收集器无法处理浮动垃圾(Floating Garbage),可能出现 “Concurent Mode Failure” 失败而导致另一次 Full GC 的产生(使用 Serial Old 收集器)。浮动垃圾指的是并发清理阶段,用户线程并发运行产生的垃圾,当这些浮动垃圾的内存超过了CMS 运行期间预留的内存,就会导致 “Concurent Mode Failure” 失败。
  3. CMS 收集器使用的标记-清除算法会有大量的内存碎片出现,将会给大对象分配带来很多麻烦。

7. G1 收集器

分区(Region)收集器,标记-整理算法和复制算法,多线程,G1(Garbage-First)收集器在 JDK 7u4 版本发布,在 JDK9 中成为默认垃圾收集器,是一款面向服务端应用的垃圾收集器,它的目标也是获得最短停顿时间。

优点:

  1. 并行和并发,缩短 Stop The World 停顿的时间。
  2. 标记-整理算法、复制算法不会出现类似 CMS 的内存碎片问题。
  3. 可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不超过 N 毫秒。

推荐场景:

G1的首要目的是为那些需要大容量内存和较小 GC 延迟的应用程序提供解决方案。这通常是指那些堆大小设置在 6GB 以上,确定的、可以预测的暂停时间在 0.5 秒以内的应用程序。

如果应用程序符合以下一项或者多项特征,那么从 CMS 或者 ParallelOld 收集器切换到 G1 可能更合适。

  • 活动对象占据了超过 50% 的 Java 堆空间。
  • 对象分配率或者提升率波动明显。
  • 不希望有长时间的垃圾收集暂停时间(超过0.5秒或1秒)。

参考链接:

  1. 《深入理解 JVM 虚拟机》
  2. G1垃圾收集器介绍
  3. jvm垃圾收集器(终结篇)

JVM系列三(垃圾收集器).的更多相关文章

  1. jvm系列 (二) ---垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...

  2. JVM笔记(三) 垃圾收集器(2)收集算法

    垃圾收集器2:收集算法 主要通过阅读<深入了解Java虚拟机>(周志明 著)和网络资源汇集而成,为本人学习JVM的笔记.同时,本文理论基于JDK 1.7版本,暂不考虑 1.8和1.9 的新 ...

  3. JVM性能优化系列-(2) 垃圾收集器与内存分配策略

    2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...

  4. JVM系列三:JVM参数设置

    JVM系列三:JVM参数设置.分析   不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM.GC的参数,可以极大的减少由于GC工作,而导致的程序运 ...

  5. 【JVM】JVM中的垃圾收集器

    垃圾收集器组合 Serial+Serial Old Serial+CMS ParNew+CMS ParNew+Serial Old Paralle Scavenge + Serial Old Para ...

  6. jvm系列(三):java GC算法 垃圾收集器

    GC算法 垃圾收集器 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计 ...

  7. jvm系列三、java GC算法 垃圾收集器

    原文链接:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 ...

  8. jvm系列(三):GC算法 垃圾收集器

    原文出处:纯洁的微笑 这篇文件将给大家介绍GC都有哪几种算法,以及JVM都有那些垃圾回收器,它们的工作原理. 概述 垃圾收集 Garbage Collection 通常被称为"GC" ...

  9. 深入理解JVM(三)垃圾收集器和内存分配策略

    3.1 关于垃圾收集和内存分配 垃圾收集和内存分配主要针对的区域是Java虚拟机中的堆和方法区: 3.2 如何判断对象是否“存活”(存活判定算法) 垃圾收集器在回收对象前判断其是否“存活”的两个算法: ...

随机推荐

  1. ZeroC ICE的远程调用框架 class与interface

    我们在ice文件中定义的class或interface,slice都会为我们生成stub存根类和skeleton骨架类.在这里要注意slice并没有分别生成两份单独用在客户端或服务端的接口给开发分发. ...

  2. Javascript脚本语言

    找组件用 id (唯一) 2.name 样式 使用分类 1 页面中 2 建JS文件 可以放在head也可以在body 工作区可以有 1 全局变量 2 由多个函数构成 标签编辑器 onChange 改变 ...

  3. 总结:mysql的各种增删改查!

    (原创总结)分为数据库的增删改查,数据表(和字段)的增删改查,数据的增删改查 三部分!// 创建用户并授权 GRANT SELECT ON bodydb.user TO us@localhost ID ...

  4. 【论文阅读】Learning Dual Convolutional Neural Networks for Low-Level Vision

    论文阅读([CVPR2018]Jinshan Pan - Learning Dual Convolutional Neural Networks for Low-Level Vision) 本文针对低 ...

  5. 2019-10-31:渗透测试,基础学习,mongodb注入学习

    mongodb命令删除文档,db.集合名.remove({键:值})更新文档,db.集合名.update({被更新的对象},{$set:{要更新的内容}}),默认只更新检测到的第一条文档更新全部匹配到 ...

  6. ASP.NET Core MVC+EF Core项目实战

    项目背景 本项目参考于<Pro Entity Framework Core 2 for ASP.NET Core MVC>一书,项目内容为party邀请答复. 新建项目 本项目开发工具为V ...

  7. Unity 工作经历+近期面试经历(二)

    注册博客园后,我原本打算每一份工作经历都记录下来.但是,这份工作已经换了半年了,好几次想要写,又不知道该怎么写.太多的负能量.我始终相信,情绪是会传染的.我基本决定放弃写这篇文章了.就让时间去淡化经历 ...

  8. String字符串为什么不可变的深入理解

    String是被final修饰的,是不可变对象,那么这句什么意思呢.在学习scala时候var,val时候,就想到这个问题,所以记录下 看案例: package com.cxy; import sun ...

  9. Glibc编译报错:*** LD_LIBRARY_PATH shouldn't contain the current directory when*** building glibc. Please change the environment variable

    执行glibc编译出错如下图 [root@localhost tmpdir]# ../configure --prefix=/usr/loacl/glibc2.9 --disable-profile ...

  10. wake on lan定时开机部署

    在Linux下通过Wake On LAN实现网络唤醒远程开机 我们经常有这样的场景或需求,人在外面,需要将家里的机器或公司的机器开启,进行远程控制操作. 有几种方式可以实现远程开机,一是通过主板的来电 ...