• windbg分析net程序内存泄漏问题


    1       问题简介

    有客户反馈,打了最新补丁后,服务器的内存暴涨,一直降不下来,程序非常卡。在客户的服务器上抓了一个dump文件,开始分析。

    分析问题的思路:

    1、找到是那些资源占用了大量内存?

    2、找到是什么原因导致内存不释放?

    3、根据分析信息定位问题代码。

    2       分析问题

    2.1  查看GC堆的内存占用情况

    Net程序大部分内存泄漏是由于没有及时垃圾回收导致的,就从GC堆开始分析。

    !eeheap -gc

     

    统计一下,有8个GC堆(因为有8个CPU核),每个堆大概在1个G左右的大小,GC堆加起来大概8个G左右。对比一下dump文件的大小为8.86个G,这个信息也就很明确了,内存都被GC堆给占用了。

     

     

    挑选heap 0来分析,发现900多M内存都在第二代里,说明对象被根引用了,没有被及时释放,导致内存泄漏。我们重点分析第二代里的对象。

    2.2 分析GC堆 heap 0的第二代对象

    分析所有堆会比较慢,我们只分析heap0的第二代对象。

     !dumpheap -stat 00000218c75d1000 0000021902a69720

     

    发现Kingdee.BOS.JSON.JSONArray,System.Object[],System.String 这三个类型占了700多M内存,就重点看上面的三个类型。

     

    2.2.1      分析System.String

    分析一下是否有大于200个字节的长字符,看看是不是超大的字符串占用了大量内存:

    !dumpheap -mt 00007ffdb9386948 -stat  -min 200 00000218c75d1000 0000021902a69720

     

     发现大字符串的数量很少,才占用3M空间,推测应该都是一些小的字符串对象,由于string对象数量有1000万左右,如果继续分析string类型,收获会比较小,搞不清楚到底是那些string对象引起的占用大量内存的。String类型肯定是被其他类型引用的, System.Object[]也是类似,所以我们重点分析Kingdee.BOS.JSON.JSONArray

     

    2.2.2       分析Kingdee.BOS.JSON.JSONArray对象

    分析Kingdee.BOS.JSON.JSONArray的方法表:!dumpheap -mt 00007ffd5c24a068  00000218c75d1000 0000021902a69720

     

    发现了有大量的40个字节的对象,ctrl+break中断一下,随机挑选一个对象,看看里面到底是什么内容。

     

    查看Kingdee.BOS.JSON.JSONArray的对象: !do 00000218cc5002a0

     

    继续查看明细项数组:items: !da 00000218cc575d60

     

     

    是一个object[]数组,看起来是Kingdee.BOS.JSON.JSONArray对象引用了object[]数组。

    继续查看数组中的对象:!do 00000218cc50b438

     

     

    发现数组的项是一个Kingdee.BOS.JSON.JSONArray对象

    继续查看对象的items数组:!da 00000218cc50b490

     

    查看最终的明细项

    !do 00000218cc50b310

    !do 00000218cc50b3a0

    能看到下面的字符串:“ABCFPZLB”,“ABC分配组列表”等字符串。

    2.2.3       查找Kingdee.BOS.JSON.JSONArray根

    找到了出问题的明细内存内容后,我们还需要找到出问题的代码到底在哪?看看能从根引用上能不能找到更多的线索。可以看看Kingdee.BOS.JSON.JSONArray对象到底是被那个根引用?

    !gcroot -nostacks 00000218cc5002a0

     

    Kingdee.BOS.JSON.JSONArray对象被缓存了,在gc句柄表被固定住了,不能被垃圾回收器回收,所以导致内存泄漏了。由于根对象列表没有发现一些更有价值的类型,我们只能通过上面的二个线索来推测问题.

    线索1、“ABCFPZLB”,“ABC分配组列表”等字符串 看起来像菜单编码、名称

    线索2、这些字符串被缓存了

     

    推断出:可能菜单信息的缓存出了问题。

     

    我们也可以看看堆栈信息,运气好的话,能从堆栈中看到一些可疑的堆栈。查看所有线程的堆栈:~*e !clrstack

     

    在这个案例中,还真是发现了可疑的堆栈

     

    GetMenuArrayForCache这个方法没有命中缓存。查看源码后发现,这个缓存的key有问题,命中率很低,导致大量重复的数据被缓存。

     

    3       经验总结

    使用缓存时,要考虑缓存的命中率,有效期。要评估一下各种情况下,缓存占用的内存可能会达到一个什么样的量。本案例的问题就是缓存的命中率低,导致了生成大量的缓存,没有及时释放引发的内存问题。

     

  • 相关阅读:
    文本框textarea根据输入内容自适应高度 和输入中文和数字换行解决方法
    switch 和 if...else if 的区别
    vue中 eCharts 自适应容器
    AJAX跨域POST发送json时,会先发送一个OPTIONS预请求
    获取鼠标和元素的坐标点
    vue2 数据交互 vue-resource
    网站代码初始化
    vue2 关于ref
    事件监听
    cookie 的 写入,读取, 删除
  • 原文地址:https://www.cnblogs.com/50614090/p/9553740.html
Copyright © 2020-2023  润新知