6

记一次内存泄露,但并未溢出的问题 #论程序员,你曾遇到关于性能的那些事#

 3 years ago
source link: https://club.perfma.com/article/2314312
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
记一次内存泄露,但并未溢出的问题 #论程序员,你曾遇到关于性能的那些事#

记一次内存泄露,但并未溢出的问题 #论程序员,你曾遇到关于性能的那些事#

changfeng1周前

起因:服务器日常巡检发现内存占用较高,一直在报警线附近。(忘记截图~~)
排查过程:
1、看了一下当时的监控图,在业务请求量不大的情况下内存占用率长期较高,且fullgc后内存占用率没有明显下降,初步推断可能存在内存泄露。于是dump出堆转储文件。使用HeapAnalyzer工具进行分析。
image.png
发现StackData类型相关对象占用堆内存过高。

2、查看代码发现,该对象被代码耗时打印工具类引用。
image.png
同时使用 ThreadLocal 存储方法调用树(对象大小受调用深度以及调用次数影响)以及调用时间。

因ThreadLocal为map数据结构。value部分为强引用,生命周期一般与线程生命周期一致。而java web容器采用线程池方式,线程长期存活,工具类未调用ThreadLocal中remove()方法释放。导致内存泄露。

另外也是因为当前场景ThreadLocal本身受到web容器线程池大小和本身业务方法调用深度限制,虽然内存泄露,但并未溢出。

3、许多工程同样引用该工具类,为何内存使用情况未有明显异常?

通过内存分析工具查看ThreadLocal对象相当一部分大小在2.8M左右,输出对象打印内容
image.png
查看该方法对应代码:
image.png

List对象CityInfo 元素有600多个,所以此处有600多次循环,会不断增大ThreadLocal大小,导致内存泄露问题突出。

问题高速我们:threadlocal 使用完成必须remove。

本文正在参与「论程序员,你曾遇到关于性能的那些事丨 PerfMa技术征文」活动


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK