游乐游手机版
首页/科技数码/文章详情

业务开发中这些场景易触发FullGC,你遇到过几个?

时间:2025-10-30 20:43
数据库连接、文件流等资源未及时关闭虽然不是严格的内存泄漏,但如果大量连接或流对象因为异常等原因没有被正确关闭,它们所关联的Java对象和native memory就无法被及时释放,也会导致内存压力激

数据库连接、文件流等资源未能及时关闭虽然不算是严格的内存泄漏,但如果大量连接或流对象由于异常等原因没有被正确关闭,它们所关联的Java对象和native memory就无法及时释放,也会导致内存压力激增,触发频繁的FullGC。

对于我们程序员来说,FullGC既是陌生的老搭档也是熟悉的老朋友。如果它偶尔发生一两次,我们其实无需刻意处理;但若频率过高,就必须及时介入,否则会影响线上用户的正常使用体验。接下来,我们来聊聊几种容易触发FullGC的典型场景。

1、实际业务中FullGC的场景分析

每当服务器接收到请求后,都需要构建各式各样的业务对象。在实际开发中,我们创建的业务对象很可能是占用空间较大的对象(如果对象体积庞大,就会直接进入老年代存储),如下图所示:

图片图片

当我们创建完业务对象后,往往还需要调用其他服务获取业务数据。假设此时调用的其他服务出现了超时(比如服务C响应超时),情况就会变成下图所示:

图片图片

一旦发生这种情况,我们创建的业务对象就会常驻在JVM内存中。假设超时时间设置为15秒,那么在这15秒内,系统中的业务对象会一直占据内存空间。若在高并发场景下频繁出现此类情况,就会导致大量业务对象长期占用内存,如下图所示:

图片图片

此时JVM中就会出现年轻代对象不断向老年代转移的现象,如下图所示:

图片图片

由于老年代空间被持续涌入的对象不断占据,最终会导致即使总剩余空间还很多,却因内存碎片化严重而无法容纳新的业务对象,进而触发FullGC。

2、整理常见的引发FullGC的原因

FullGC会对老年代和新生代同时进行回收,通常还会伴随对元空间(或永久代)的清理,这往往会引起服务停顿,直接影响线上业务。

(1)老年代空间不足

当对象需要被分配到老年代,但老年代剩余空间无法满足需求时,就会触发FullGC。长期存活的对象不断进入老年代,正是导致老年代空间不足的常见原因。

JVM为每个对象定义了一个年龄计数器(记录在对象头中)。对象在Eden区诞生,经历一次YoungGC后若仍然存活,就会被移动到Survivor区,并且年龄增加1。当它的年龄增长到一定程度(默认为15,也可以通过参数调整),下一次Young GC时就会被晋升到老年代。如果此时老年代空间不足,就会触发Full GC。

(2)空间分配担保失败

在准备触发一次YoungGC时,会执行空间分配担保检查。在担保过程中,如果虚拟机检测到老年代最大可用连续空间小于新生代所有对象总空间,且HandlePromotionFailure=false(这个设置在jdk7中已不再支持,这一步骤在jdk7以后版本已被取消),那么就会执行一次FullGC。

在准备触发一次YoungGC时,会进行空间分配担保,在担保过程中发现老年代最大可用连续空间小于新生代所有对象的总空间,但是HandlePromotionFailure=true,继续检查发现老年代最大可用连续空间小于历次晋升到老年代对象的平均大小时,就会触发一次FullGC。

(3)调用 System.gc() 方法

在代码中直接调用System.gc()或Runtime.getRuntime().gc()会建议 JVM 执行 FullGC。需要注意的是这里只是建议,并非强制,但大多数情况下JVM都会执行。为了避免开发人员滥用,通常我们会通过参数-XX:+DisableExplicitGC来禁止这种显式的GC调用。

(4)内存泄漏

虽然老年代总空间很大,但如果存在内存泄漏,一些"垃圾对象"因为被意外的引用持有而无法被回收(典型的有ThreadLocal使用不当就会出现内存泄漏的问题)。每次YoungGC后,都有一批本应被回收的对象因为泄漏而被迫进入老年代,最终导致老年代空间使用达到回收阈值,触发FullGC。

(5)老年代碎片化严重

如果YoungGC后Survivor区存活对象正常晋升到老年代,但老年代也因碎片化严重而无法容纳这些对象,那么即使总的剩余空间还很充裕,也会触发FullGC来整理碎片。

偶尔一次FullGC通常不会造成问题,但如果FullGC频繁发生或者单次FullGC持续时间过长,这些都是需要我们重点关注的情况。

3、实际业务中常见的易导致FullGC场景

(1)雪崩效应

在系统中依赖其他服务返回的响应数据,如果其他服务返回响应超时,容易导致当前内存中数据激增进而触发FullGC。

(2)大对象分配

文件处理是常见业务场景,在解析文件时,如果用户上传一个上百兆的大文件,服务端一次性将其读入内存数组中,那么这个数组就是一个大对象,很可能直接在老年代分配。如果此时有多个用户同时上传大文件,就会迅速挤占老年代空间,进而触发FullGC。

(3)内存泄漏

一个后台任务系统,需要缓存一些任务执行上下文,开发人员常见的处理方案是将这些上下文对象放入一个静态的HashMap中(或者使用ThreadLocal)。由于静态集合的生命周期与类加载器相同(通常就是程序运行期间),这些上下文对象永远无法被回收。随着系统持续运行,这个HashMap会越来越大,最终导致老年代内存不足,触发频繁的FullGC。

(4)资源未关闭

数据库连接、文件流等资源未能及时关闭虽然不算是严格的内存泄漏,但如果大量连接或流对象因为异常等原因没有被正确关闭,它们所关联的Java对象和native memory就无法及时释放,也会导致内存压力激增,触发频繁的FullGC。

来源:https://www.51cto.com/article/828157.html
上一篇VexDB迈向DB4AI:探索首个成功实践的关键路径 下一篇解密MinIO开源转型:技术栈痛点分析与替代方案
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
女乘客凌晨网约车上排泄后逃逸 司机获赔三千元
科技数码 · 2026-05-30

女乘客凌晨网约车上排泄后逃逸 司机获赔三千元

网约车司机每天起早贪黑,接到的乘客形形色色,按理说早已见惯了各种突发状况。但最近刷到一则令人极度窒息、又无比心疼网约车司机的新闻,真的越看越让人无语。5月27日凌晨3点多,四川南充的网约车司机陈师傅像往常一样跑夜班,接到一名女性乘客。这名乘客竟然在网约车上排便,完事后还若无其事地下车跑了!图源:微博

中国十年研发气固电池 氢能车告别高压风险
科技数码 · 2026-05-30

中国十年研发气固电池 氢能车告别高压风险

中国科学院大连化学物理研究所研发全球首例气-固氢负离子原型电池,以氢气为正极、金属镁为负极,实现常温常压储氢。储氢效率达93 9%,可在-20℃至90℃稳定工作,循环60次容量保持率超70%,为氢能储运提供安全高效新路径。

vivo TWS 5e耳机发布 3色可选55dB混合自适应降噪229元
科技数码 · 2026-05-30

vivo TWS 5e耳机发布 3色可选55dB混合自适应降噪229元

vivoTWS5e耳机全新发布,售价仅为229元,提供留白、墨黑、天青三种配色。单耳仅重4 3克,支持IP54防尘防水。搭载55dB混合自适应降噪及双麦克风AI通话降噪,配备11mm动圈单元,蓝牙5 4,延迟低至仅42ms,配合充电盒总续航可达55小时,性价比极高。

罗永浩新号粉丝破400万 力挺杨笠后逆袭翻盘
科技数码 · 2026-05-30

罗永浩新号粉丝破400万 力挺杨笠后逆袭翻盘

提到罗永浩,他新开通的社交账号粉丝数已经突破400万大关。不愧是“初代网红”中的流量担当,这涨粉速度令人惊叹。粉丝数量攀升后,罗永浩随即宣布将举办抽奖活动,赠送礼物以回馈支持者。图片来源:微博平心而论,这个数据并不令人意外。罗永浩在互联网领域摸爬滚打多年,尽管时常在“争议”与“反转”之间游走,但他对

英伟达微软发布神秘预告PC芯片下周亮相
科技数码 · 2026-05-30

英伟达微软发布神秘预告PC芯片下周亮相

北京时间周六凌晨,微软与英伟达几乎同步在社交媒体上为一款即将于下周亮相的神秘新品造势预热,二者联手的举动引发广泛关注,颇有“联手合作”的意味。 微软方面,Windows与Surface硬件部门执行副总裁帕万·达武鲁里(Pa van Da vuluri)晒出一张照片,隐约可见曲面屏边缘,配文表示:“为