前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一次腾讯云COS SDK线上内存泄漏问题总结

一次腾讯云COS SDK线上内存泄漏问题总结

原创
作者头像
卡卡罗特杨
发布2023-05-25 10:35:04
1.1K0
发布2023-05-25 10:35:04
举报

JVM内存泄露是Java应用程序中常见的问题之一。当应用程序在运行时,如果没有正确地释放内存,就会导致内存泄露。这会导致应用程序的性能下降,甚至会导致应用程序崩溃。本文将分享一次对腾讯云COS SDK线上内存泄漏问题排查的过程。并对Java泄漏问题的处理方法进行一些总结,期望能帮助到正在被Java内存泄漏困扰着的同学。

业务系统配置

1)JDK的版本信息

openjdk version "1.8.0_232"

OpenJDK Runtime Environment (Tencent Kona 8.0.0-internal) (build 1.8.0_232-86)

OpenJDK 64-Bit Server VM (Tencent Kona 8.0.0-internal) (build 25.232-b86, mixed mode, sharing)

2)JVM的配置信息

-server -Xms4g -Xmx4g 

-XX:ActiveProcessorCount=4 

-XX:+UseAdaptiveSizePolicy 

  项目的业务场景是一个后台的定时任务,每天凌晨1点调用腾讯COS SDK拉取云COS相关的备份信息,并记录数据库,以便运营进行业务分析。考虑后台任务不用关注延迟,因为用了默认Parallel Scavenge(新生代)+Parallel Old(老年代),并开启UseAdaptiveSizePolicy自动调节新生代大小比例。

问题状况和排查过程

   项目上线运行一段时间以后,运营反馈数据更新有延迟。上线排查,发现日志存在大量的java.lang.OutOfMemoryError:GC overhead limit exceeded日志信息。怀疑是跟内存泄漏有关。因此重启服务 ,启动参数加上-XX:+HeapDumpOnOutOfMemoryError 和-XX:HeapDumpPath参数,这样就可以让JVM发生内存泄漏时候自动触发dump。

  通过MAT分析,发现存在大量的PoolingHttpClientConnectionManager,占了近2.5个G。

   通过OQL查询 一共有9366个对象实例,平均每个对象实例的Retained Heap占有295928个字节,换算一下9366 * 295928 =  2771661648 = 2.58131G,因此也符合上图所展示的数据。

   查看引用情况,可以看到有9364个对象实例是被com.qcloud.cos.http.IdleConnectionMonitorThread引用

   通过进一步分析,可以看到com.qcloud.cos.http.IdleConnectionMonitorThread是由com.qcloud.cos.http.DefaultCosHttpClient创建,CosHttpClient又由COSClient创建。

  因此这个链路就比较清晰,即是:

PoolingHttpClientConnectionManager -》IdleConnectionMonitorThread -》DefaultCosHttpClient -》COSClient

  而COSClient正是用于获取腾讯云COS备份信息,因此问题也跟业务背景相关。

  于是查源代码,可以看到每次创建一个DefaultCosHttpClient都会生成PoolingHttpClientConnectionManager和IdleConnectionMonitorThread的实例对象,并且将connectionManager作为参数传人到idleConnectionMonitor的构造函数中。

  查看IdleConnectionMonitorThread的具体实现,可以看到继承了Thread,是一个线程类。在调用上图中调用strart()方法,将会开启一个异步线程任务。

  IdleConnectionMonitorThread主要包含run和shutdown两个方法。

  在run方法中,循环判断shutdown变量为false时,等待2000MS,然后清除connMgr的无效链接。

  可以看到shutdown变量,是一个被volatile修饰的boolean值,这样就保证线程间的可见性。默认shutdown变量为false,一旦调用shutdown方法,shutdown变量将被设置为true,调用notifyAll()进行线程唤醒。此时run方法将立即执行剩余方法,并在下次循环中判断shutdown为true,跳出当前循环。

  此时当前idleConnectionMonitor的线程实例,由于线程任务已经执行完,将会被关闭。

  在下次GC回收时候,idleConnectionMonitor作为无效的GC Root会被回收。那么它所引用的connMgr,也就是前面的PoolingHttpClientConnectionManager的对象实例,通过可达性分析,将会被标记为不可达,也会一起被GC回收。

  通过如上所推论,需要在使用COSClient以后,通过shutdown方法,关闭IdleConnectionMonitorThread这个监控线程,从而回收PoolingHttpClientConnectionManager。

  查看业务代码,确实没有加上shutdown方法。因此随着时间积累,将产生大量无法回收的PoolingHttpClientConnectionManager的对象实例,从而最终导致内存泄漏。

  因此修改业务代码,加上shutdown方法以后,目前系统稳定运行,内存也恢复正常。

问题和总结

  在查阅腾讯云官网时候,确实发现有相关的提示,但提示并非很明显。在实际线上场景,会存在遗漏相关代码,造成内存泄漏现象。

  因此对于JVM的内存泄漏问题,除了在平时写代码时候,需要认真仔细以外。在发生线上故障时候,能通过经验和工具进行问题排查,也是很重要一部份。

  关于如何处理线上JVM内存泄露问题,可以从以下几方面考虑:

一、识别内存泄露

  首先,需要识别内存泄露。可以通过JVM的内存监控工具来检测内存泄露。例如,可以使用JConsole或VisualVM等工具来监控JVM的内存使用情况。如果发现内存使用量不断增加,而且没有明显的回收迹象,那么就有可能存在内存泄露。

二、分析内存泄露原因

1. Heap Dump快照:Heap Dump是JVM在应用程序运行时生成的内存快照。可以使用MAT(Memory Analyzer Tool)等工具来分析Heap Dump。通过分析Heap Dump,可以找到内存泄露的对象和引用链。这有助于找到内存泄露的原因。

Heap Dump快照有两种方式:

1)在启动参数加上-XX:+HeapDumpOnOutOfMemoryError 和-XX:HeapDumpPath参数

2)jmap命令:用于生成JVM的内存快照。例如,可以使用以下命令生成JVM的内存快照:

代码语言:javascript
复制
jmap -dump:format=b,file=heap.bin 

2. Java自带的工具:

jstat命令:用于监控JVM的状态。例如,可以使用以下命令监控JVM的垃圾回收情况:

代码语言:javascript
复制
jstat -gc   

     jstack命令:用于生成Java线程的堆栈信息。例如,可以使用以下命令生成Java线程的堆栈信息:

代码语言:javascript
复制
jstack <pid>

三、修复内存泄露

  一旦找到内存泄露的原因,就需要修复内存泄露。修复内存泄露的方法因情况而异。以下是一些常见的修复方法:

1. 关闭资源:如果应用程序使用了一些资源,例如数据库连接、文件句柄等,那么需要在使用完后及时关闭这些资源,以释放内存。

2. 优化代码:如果应用程序中存在一些不必要的对象创建和引用,那么可以通过优化代码来减少内存使用量。

3. 调整JVM参数:可以通过调整JVM参数来优化内存使用。例如,可以增加堆内存大小、调整垃圾回收策略等。

4. 使用内存泄露检测工具:可以使用一些内存泄露检测工具来帮助识别和修复内存泄露。例如,可以使用Eclipse Memory Analyzer等工具来检测内存泄露。

四、预防内存泄露

  最后,需要预防内存泄露。以下是一些预防内存泄露的方法:

1. 及时释放资源:在使用完资源后,需要及时释放资源,以避免内存泄露。

2. 避免创建不必要的对象:在编写代码时,需要避免创建不必要的对象,以减少内存使用量。

3. 使用缓存:可以使用缓存来避免重复创建对象,以减少内存使用量。

4. 定期检查内存使用情况:定期检查内存使用情况,可以及时发现内存泄露问题,并采取相应的措施。

  总之,解决线上JVM内存泄露需要识别内存泄露、分析内存泄露原因、修复内存泄露和预防内存泄露。通过以上方法,可以有效地解决线上JVM内存泄露问题。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 业务系统配置
  • 问题状况和排查过程
  • 问题和总结
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档