网易首页 > 网易号 > 正文 申请入驻

5种JVM垃圾收集器特点和8种JVM内存溢出原因

0
分享至

一、常见垃圾收集器

现在常见的垃圾收集器有如下几种:

新生代收集器:

  • Serial

  • ParNew

  • Parallel Scavenge

老年代收集器:

  • Serial Old

  • CMS

  • Parallel Old

堆内存垃圾收集器:G1

每种垃圾收集器之间有连线,表示他们可以搭配使用。

二、新生代垃圾收集器

(1)Serial 收集器

Serial 是一款用于新生代的单线程收集器,采用复制算法进行垃圾收集。Serial 进行垃圾收集时,不仅只用一条线程执行垃圾收集工作,它在收集的同时,所有的用户线程必须暂停(Stop The World)。

就比如妈妈在家打扫卫生的时候,肯定不会边打扫边让儿子往地上乱扔纸屑,否则一边制造垃圾,一遍清理垃圾,这活啥时候也干不完。

如下是 Serial 收集器和 Serial Old 收集器结合进行垃圾收集的示意图,当用户线程都执行到安全点时,所有线程暂停执行,Serial 收集器以单线程,采用复制算法进行垃圾收集工作,收集完之后,用户线程继续开始执行。

适用场景:Client 模式(桌面应用);单核服务器。

可以用 -XX:+UserSerialGC 来选择 Serial 作为新生代收集器。

(2)ParNew 收集器

ParNew 就是一个 Serial 的多线程版本,其它与Serial并无区别。ParNew 在单核 CPU 环境并不会比 Serial 收集器达到更好的效果,它默认开启的收集线程数和 CPU 数量一致,可以通过 -XX:ParallelGCThreads 来设置垃圾收集的线程数。

如下是 ParNew 收集器和 Serial Old 收集器结合进行垃圾收集的示意图,当用户线程都执行到安全点时,所有线程暂停执行,ParNew 收集器以多线程,采用复制算法进行垃圾收集工作,收集完之后,用户线程继续开始执行。

适用场景:多核服务器;与 CMS 收集器搭配使用。当使用 -XX:+UserConcMarkSweepGC 来选择 CMS 作为老年代收集器时,新生代收集器默认就是 ParNew,也可以用 -XX:+UseParNewGC 来指定使用 ParNew 作为新生代收集器。

(3)Parallel Scavenge 收集器

Parallel Scavenge 也是一款用于新生代的多线程收集器,与 ParNew 的不同之处是ParNew 的目标是尽可能缩短垃圾收集时用户线程的停顿时间,Parallel Scavenge 的目标是达到一个可控制的吞吐量。

吞吐量就是 CPU 执行用户线程的的时间与 CPU 执行总时间的比值【吞吐量 = 运行用户代代码时间/(运行用户代码时间+垃圾收集时间)】,比如虚拟机一共运行了 100 分钟,其中垃圾收集花费了 1 分钟,那吞吐量就是 99% 。比如下面两个场景,垃圾收集器每 100 秒收集一次,每次停顿 10 秒,和垃圾收集器每 50 秒收集一次,每次停顿时间 7 秒,虽然后者每次停顿时间变短了,但是总体吞吐量变低了,CPU 总体利用率变低了。

可以通过 -XX:MaxGCPauseMillis 来设置收集器尽可能在多长时间内完成内存回收,可以通过 -XX:GCTimeRatio 来精确控制吞吐量。

如下是 Parallel 收集器和 Parallel Old 收集器结合进行垃圾收集的示意图,在新生代,当用户线程都执行到安全点时,所有线程暂停执行,ParNew 收集器以多线程,采用复制算法进行垃圾收集工作,收集完之后,用户线程继续开始执行;在老年代,当用户线程都执行到安全点时,所有线程暂停执行,Parallel Old 收集器以多线程,采用标记整理算法进行垃圾收集工作。

适用场景:注重吞吐量,高效利用 CPU,需要高效运算且不需要太多交互。

可以使用 -XX:+UseParallelGC 来选择 Parallel Scavenge 作为新生代收集器,jdk7、jdk8 默认使用 Parallel Scavenge 作为新生代收集器。

三、老年代垃圾收集器

(1)Serial Old 收集器

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

如下图是 Serial 收集器和 Serial Old 收集器结合进行垃圾收集的示意图:

适用场景:Client 模式(桌面应用);单核服务器;与 Parallel Scavenge 收集器搭配;作为 CMS 收集器的后备预案。

(2)CMS(Concurrent Mark Sweep) 收集器

CMS 收集器是一种以最短回收停顿时间为目标的收集器,以 “ 最短用户线程停顿时间 ” 著称。整个垃圾收集过程分为 4 个步骤:

① 初始标记:标记一下 GC Roots 能直接关联到的对象,速度较快。

② 并发标记:进行 GC Roots Tracing,标记出全部的垃圾对象,耗时较长。

③ 重新标记:修正并发标记阶段引用户程序继续运行而导致变化的对象的标记记录,耗时较短。

④ 并发清除:用标记-清除算法清除垃圾对象,耗时较长。

整个过程耗时最长的并发标记和并发清除都是和用户线程一起工作,所以从总体上来说,CMS 收集器垃圾收集可以看做是和用户线程并发执行的。

对 CPU 资源敏感:默认分配的垃圾收集线程数为(CPU 数+3)/4,随着 CPU 数量下降,占用 CPU 资源越多,吞吐量越小

无法处理浮动垃圾:在并发清理阶段,由于用户线程还在运行,还会不断产生新的垃圾,CMS 收集器无法在当次收集中清除这部分垃圾。同时由于在垃圾收集阶段用户线程也在并发执行,CMS 收集器不能像其他收集器那样等老年代被填满时再进行收集,需要预留一部分空间提供用户线程运行使用。当 CMS 运行时,预留的内存空间无法满足用户线程的需要,就会出现 “ Concurrent Mode Failure ”的错误,这时将会启动后备预案,临时用 Serial Old 来重新进行老年代的垃圾收集。

因为 CMS 是基于标记-清除算法,所以垃圾回收后会产生空间碎片,可以通过 -XX:UserCMSCompactAtFullCollection 开启碎片整理(默认开启),在 CMS 进行 Full GC 之前,会进行内存碎片的整理。还可以用 -XX:CMSFullGCsBeforeCompaction 设置执行多少次不压缩(不进行碎片整理)的 Full GC 之后,跟着来一次带压缩(碎片整理)的 Full GC。

适用场景:重视服务器响应速度,要求系统停顿时间最短。可以使用 -XX:+UserConMarkSweepGC 来选择 CMS 作为老年代收集器。

(3)Parallel Old 收集器

Parallel Old 收集器是 Parallel Scavenge 的老年代版本,是一个多线程收集器,采用标记-整理算法。可以与 Parallel Scavenge 收集器搭配,可以充分利用多核 CPU 的计算能力。

适用场景:与Parallel Scavenge 收集器搭配使用;注重吞吐量。jdk7、jdk8 默认使用该收集器作为老年代收集器,使用 -XX:+UseParallelOldGC 来指定使用 Paralle Old 收集器。

四、新生代和老年代垃圾收集器

G1 收集器

G1 收集器是 jdk1.7 才正式引用的商用收集器,现在已经成为 jdk9 默认的收集器。前面几款收集器收集的范围都是新生代或者老年代,G1 进行垃圾收集的范围是整个堆内存,它采用 “ 化整为零 ” 的思路,把整个堆内存划分为多个大小相等的独立区域(Region),在 G1 收集器中还保留着新生代和老年代的概念,它们分别都是一部分 Region,如下图:

每一个方块就是一个区域,每个区域可能是 Eden、Survivor、老年代,每种区域的数量也不一定。JVM 启动时会自动设置每个区域的大小(1M ~ 32M,必须是 2 的次幂),最多可以设置 2048 个区域(即支持的最大堆内存为 32M*2048 = 64G),假如设置 -Xmx8g -Xms8g,则每个区域大小为 8g/2048=4M。

为了在 GC Roots Tracing 的时候避免扫描全堆,在每个 Region 中,都有一个 Remembered Set 来实时记录该区域内的引用类型数据与其他区域数据的引用关系(在前面的几款分代收集中,新生代、老年代中也有一个 Remembered Set 来实时记录与其他区域的引用关系),在标记时直接参考这些引用关系就可以知道这些对象是否应该被清除,而不用扫描全堆的数据。

G1 收集器可以 “ 建立可预测的停顿时间模型 ”,它维护了一个列表用于记录每个 Region 回收的价值大小(回收后获得的空间大小以及回收所需时间的经验值),这样可以保证 G1 收集器在有限的时间内可以获得最大的回收效率。

如下图所示,G1 收集器收集器收集过程有初始标记、并发标记、最终标记、筛选回收,和 CMS 收集器前几步的收集过程很相似:

① 初始标记:标记出 GC Roots 直接关联的对象,这个阶段速度较快,需要停止用户线程,单线程执行。

② 并发标记:从 GC Root 开始对堆中的对象进行可达新分析,找出存活对象,这个阶段耗时较长,但可以和用户线程并发执行。

③ 最终标记:修正在并发标记阶段引用户程序执行而产生变动的标记记录。

④ 筛选回收:筛选回收阶段会对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来指定回收计划(用最少的时间来回收包含垃圾最多的区域,这就是 Garbage First 的由来——第一时间清理垃圾最多的区块),这里为了提高回收效率,并没有采用和用户线程并发执行的方式,而是停顿用户线程。

适用场景:要求尽可能可控 GC 停顿时间;内存占用较大的应用。可以用 -XX:+UseG1GC 使用 G1 收集器,jdk9 默认使用 G1 收集器。

五、JVM垃圾收集器总结

本文主要介绍了JVM中的垃圾回收器,主要包括串行回收器、并行回收器以及CMS回收器、G1回收器。他们各自都有优缺点,通常来说你需要根据你的业务,进行基于垃圾回收器的性能测试,然后再做选择。下面给出配置回收器时,经常使用的参数:

-XX:+UseSerialGC:在新生代和老年代使用串行收集器-XX:+UseParNewGC:在新生代使用并行收集器-XX:+UseParallelGC :新生代使用并行回收收集器,更加关注吞吐量-XX:+UseParallelOldGC:老年代使用并行回收收集器-XX:ParallelGCThreads:设置用于垃圾回收的线程数-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器-XX:ParallelCMSThreads:设定CMS的线程数量-XX:+UseG1GC:启用G1垃圾回收器

接下来看看8种JVM内存溢出原因

一. Java 堆空间

发生频率:5颗星

造成原因

  • 无法在 Java 堆中分配对象

  • 吞吐量增加

  • 应用程序无意中保存了对象引用,对象无法被 GC 回收

  • 应用程序过度使用 finalizer。finalizer 对象不能被 GC 立刻回收。finalizer 由结束队列服务的守护线程调用,有时 finalizer 线程的处理能力无法跟上结束队列的增长

解决方案

  • 使用 -Xmx 增加堆大小

  • 修复应用程序中的内存泄漏

二. GC 开销超过限制

发生频率:5颗星

造成原因

  • Java 进程98%的时间在进行垃圾回收,恢复了不到2%的堆空间,最后连续5个(编译时常量)垃圾回收一直如此。

解决方案

  • 使用 -Xmx 增加堆大小

  • 使用 -XX:-UseGCOverheadLimit 取消 GC 开销限制

  • 修复应用程序中的内存泄漏

三. 请求的数组大小超过虚拟机限制

发生频率:2颗星

造成原因

  • 应用程序试图分配一个超过堆大小的数组

解决方案

  • 使用 -Xmx 增加堆大小

  • 修复应用程序中分配巨大数组的 bug

四. Perm gen 空间

发生频率:3颗星

造成原因

Perm gen 空间包含:

  • 类的名字、字段、方法

  • 与类相关的对象数组和类型数组

  • JIT 编译器优化

当 Perm gen 空间用尽时,将抛出异常。

解决方案

  • 使用 -XX: MaxPermSize 增加 Permgen 大小

  • 不重启应用部署应用程序可能会导致此问题。重启 JVM 解决

五. Metaspace

发生频率:3颗星

造成原因

  • 从 Java 8 开始 Perm gen 改成了 Metaspace,在本机内存中分配 class 元数据(称为 metaspace)。如果 metaspace 耗尽,则抛出异常

解决方案

  • 通过命令行设置 -XX: MaxMetaSpaceSize 增加 metaspace 大小

  • 取消 -XX: maxmetsspacedize

  • 减小 Java 堆大小,为 MetaSpace 提供更多的可用空间

  • 为服务器分配更多的内存

  • 可能是应用程序 bug,修复 bug

六. 无法新建本机线程

发生频率:5颗星

造成原因

  • 内存不足,无法创建新线程。由于线程在本机内存中创建,报告这个错误表明本机内存空间不足

解决方案

  • 为机器分配更多的内存

  • 减少 Java 堆空间

  • 修复应用程序中的线程泄漏。

  • 增加操作系统级别的限制

  • ulimit -a

  • 用户进程数增大 (-u) 1800

  • 使用 -Xss 减小线程堆栈大小

七. 杀死进程或子进程

发生频率:1颗星

造成原因

  • 内核任务:内存不足结束器,在可用内存极低的情况下会杀死进程

解决方案

  • 将进程迁移到不同的机器上

  • 给机器增加更多内存

  • 与其他 OOM 错误不同,这是由操作系统而非 JVM 触发的。

八. 发生 stack_trace_with_native_method

发生频率:1颗星

造成原因

  • 本机方法(native method)分配失败

  • 打印的堆栈跟踪信息,最顶层的帧是本机方法

解决方案

  • 使用操作系统本地工具进行诊断


最后

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
4月26俄乌:美国再宣布60亿援乌计划,新战略达成,一切为时不晚

4月26俄乌:美国再宣布60亿援乌计划,新战略达成,一切为时不晚

山河路口
2024-04-26 17:42:04
广东宏远男篮半决赛对阵辽宁男篮的赛程安排(建议收藏)

广东宏远男篮半决赛对阵辽宁男篮的赛程安排(建议收藏)

林子说事
2024-04-27 00:22:37
万达将面临生死劫,留给王健林的时间仅1个月,怪不得思聪低调了

万达将面临生死劫,留给王健林的时间仅1个月,怪不得思聪低调了

通文知史
2023-11-24 16:45:59
拉基蒂奇:14/15赛季欧冠冠军是欧冠历史上含金量最高的一届

拉基蒂奇:14/15赛季欧冠冠军是欧冠历史上含金量最高的一届

懂球帝
2024-04-26 11:27:09
为抗议美国对加沙政策,美国务院发言人辞职

为抗议美国对加沙政策,美国务院发言人辞职

环球时报国际
2024-04-26 14:19:54
很多地方把“为人民服务”变成“为大局服务”,这两者有啥区别?

很多地方把“为人民服务”变成“为大局服务”,这两者有啥区别?

翻开历史和现实
2024-04-25 13:12:17
纪云浩前途尽毁!涉嫌学历造假、荣誉造假,父亲身份疑似遭曝光

纪云浩前途尽毁!涉嫌学历造假、荣誉造假,父亲身份疑似遭曝光

叶公子
2024-04-24 20:45:23
美国人坦言浙江不可怕,可怕的是凌晨三点钟,浙江街道上还全是人

美国人坦言浙江不可怕,可怕的是凌晨三点钟,浙江街道上还全是人

原广工业
2024-04-26 21:57:44
G4上海112-107战胜浙江,来看赛后王哲林说了什么?

G4上海112-107战胜浙江,来看赛后王哲林说了什么?

篮球资讯达人
2024-04-27 01:48:52
“阻拦春耕副书记”纪云浩大学学历来自政法系统定向培养?相关部门回应:2016年前确有专项招录

“阻拦春耕副书记”纪云浩大学学历来自政法系统定向培养?相关部门回应:2016年前确有专项招录

上游新闻
2024-04-25 19:46:07
限期180天,美要求中国军工企业退出俄市场,否则就全面封锁制裁

限期180天,美要求中国军工企业退出俄市场,否则就全面封锁制裁

环球Talk
2024-04-23 23:47:26
掘金主帅更衣室演讲:虽然3比0领先,但还有很多地方需要改进

掘金主帅更衣室演讲:虽然3比0领先,但还有很多地方需要改进

懂球帝
2024-04-26 19:16:22
谭秦东:“我没靠山的软柿子,万幸当年能活下来”,300多人打赏

谭秦东:“我没靠山的软柿子,万幸当年能活下来”,300多人打赏

汉史趣闻
2024-04-25 15:54:53
村支书向麦田排污后续!多部门介入,村支书秒怂:上级让我干的

村支书向麦田排污后续!多部门介入,村支书秒怂:上级让我干的

洛洛女巫
2024-04-26 16:26:03
三个反美的国家,紧紧地抱在了一起!

三个反美的国家,紧紧地抱在了一起!

3号视频
2024-04-24 14:33:16
常德市委书记调整

常德市委书记调整

新京报政事儿
2024-04-26 18:11:09
发裸照,性骚扰,贵圈又爆了一个大瓜

发裸照,性骚扰,贵圈又爆了一个大瓜

独立鱼
2024-04-25 23:45:54
越南一工厂因订单不足,给工人无薪放假,遭遇集体大罢工,许多女工表示:这是逼我们辞职

越南一工厂因订单不足,给工人无薪放假,遭遇集体大罢工,许多女工表示:这是逼我们辞职

越南语学习平台
2024-04-26 10:38:38
赖清德喊话中国,让大陆接纳台湾民进党政府,两岸展开自信交流

赖清德喊话中国,让大陆接纳台湾民进党政府,两岸展开自信交流

慕容青霄
2024-04-26 13:11:32
噩耗!34岁网红珍珍去世,每天直播健身瘦45斤,知情人曝原因!

噩耗!34岁网红珍珍去世,每天直播健身瘦45斤,知情人曝原因!

花花lo先森
2024-04-26 10:51:04
2024-04-27 02:34:44
程序员追风
程序员追风
Java架构学习经验分享
190文章数 5811关注度
往期回顾 全部

头条要闻

官方回应环卫工用电子秤测灰尘:正常作业达标有奖励

头条要闻

官方回应环卫工用电子秤测灰尘:正常作业达标有奖励

体育要闻

还得等!记者:恩昆库本周尝试参加训练 但又被退回医疗中心

娱乐要闻

金靖回应不官宣恋情结婚的原因

财经要闻

贾跃亭,真他娘是个人才

科技要闻

车展观察|德系日系绝不能放弃中国市场

汽车要闻

2024北京车展 比亚迪的自驱力让对手紧追猛赶

态度原创

家居
本地
教育
健康
公开课

家居要闻

光影之间 空间暖意打造生活律动

本地新闻

蛋友碰碰会空降西安!5.1山海境等你!

教育要闻

湖南中考因式分解题,给你10秒想思路,做起来就容易了

这2种水果可降低高血压死亡风险

公开课

睡前进食会让你发胖吗?

无障碍浏览 进入关怀版