zoukankan      html  css  js  c++  java
  • GC堆中的“内存泄漏”

    首先介绍一下程序,Server程序,同时有好多Client连接,Client用tcpSocket发送数据给Server,Server对数据进行处理并返回处理结果给Client。虽然整个程序的开发时间很长,但中间不停的需求变更,功能不停地增加减少,代码也是好多人,每人几个模块甚至是几个函数杂凑起来,系统正在被使用,功能也不断被增加,总之......是一个SHZY初级阶段特色的绝对代表的Server程序。
     
    这是我接手这个程序之后的一些Bug的发现和修改,把他记录下来,以做茶余饭后的谈资。
     
    对于这种要文档没文档、要规范没规范程序,要在一边添加新功能,一边发现和修改bug是极其困难的,如果没有一些大杀器,不太好搞,而一但有了一些大杀器,对于有些问题的发现以及解决又简单到令人发指,WinDbg就是这样一种大杀器。

            程序一天部署好几次,没办法,bug太多了,催的又急,每次修改一下就赶紧部署了,某天突然有个经理电话里喊道,你这程序内存怎么越用越大,幸好哥早有防备,呃,经理,先别着急,请双击一下桌面的“Server.Bat”,然后重新启动一下程序(重新启动一下内存就小了哈)。

    1。首先对程序的运行有个大概的了解。(比如说 程序运行了多长时间,内存多大)

    登到服务器上一看,我的天, dump文件1.8G---程序大概是2个小时之前部署

    打开windbg,打开dump,呃,程序运行了2个半小时。

            设置上符号地址,然后加载sos

           2。查看GC堆上的内存占用是多大。(一般来讲,内存泄露都是GC堆上的问题,也就是说new了一些对象在某些情况下没有释放,!EEHeap -GC 正是查看GC堆得命令,我们看到

    最后一行GC Heap Size是1.2G,1.8G的内存,GC堆1.2G,肯定有问题了,当然,Loader堆也不大可能有600M,以后我会对Loader堆继续分析。。。

           第一个命令  !EEHeap -GC

           

            3。确定是GC堆的问题,就看看GC堆上存活的对象是那些。(!dumpheap -stat 就是GC堆上的统计,我们看到统计结果,第一行SingnallingContex,  00000644803111a0  是该对象的MethondTable的地址,而186402是该对象在内存中的个数,35789184是大小,这是纯净的大小,该对象里面所包含的对象的大小不算在内,看到Context相关联的ProcessDetail竟然有5325513个,所占字节为488804488,这足够惊人了。。。 

           呃,看到这里都能猜想到,Loader堆里肯定有很多垃圾,先不管这么多了[我会在后续中介绍Loader堆里面的事情],先看看GC堆里有什么,第二个命令!DumpHeap -stat。

           

           看到一个很熟悉的名字 “SingallingContext”,这是一个Context,这个Context是接收到数据之后包装一下经过业务的pipfilter。1W多个,而Context上多呆的ProcessDetail竟然到了百万,猜测是某个处理Module缓存住了,没有释放。

     4。确定了是哪种类型对象的问题,那就看看该对象。( !Dumpheap -mt 00000644803111a0  你也可以用 !Dumpheap -type SingnallingContex 这个命令

    于是 第三个命令 !Dumpheap -mt 00000644803111a0   

           

           5。找到其中一个对象,看看是因为谁的引用而没有释放(!gcroot +对象地址 这个命令就可以得到这个对象的“根”,这个过程会非常长,具体讲该命令将会遍历所有的根,我们看到Scan Thread 67 实际上就是在扫描67号线程的线程Stack是不是引用了该对象。)

    额,这么多,随便找一个,就找最后一个吧,第四个命令 !gcroot 00000001677ceda8,这个时候该去厕所抽支烟.... 

     

     6。我们找到了“罪魁祸首”的对象,一般我们看看代码就OK了。(这里闲的无聊的话我们可以看看这个对象到底占了多大的内存,!objsize +对象地址,我们就看到了,这个命令时间非常长,长到你可以蹲着抽烟)

    额,看到根了,SingallingContextTracer,这个东西是个跟踪器,不会是跟踪器没有释放吧??先不管,看看多大,第五个命令 !objsize 00000000c1707658 

     

           

    打开代码,找到SingallingContextTracer,呃,这个可怜的家伙把每个Context放到自己的Queue中,然后开启另外的线程来处理,可惜处理线程被谁注释掉了(跟踪功能因为没啥用处,被去掉了,但是去掉了应该不让入队啊),好吧,赶紧修改代码,重新部署......
     

     BTW:贴图排版好累啊,怎样容易排版一些啊?

    -----------------------------------------------------------------------------------------------------

    总结:

    1.对程序大概了解,知己知彼。

    2.确定什么地方引起的泄露,是GC堆还是什么Loader堆等。

    3.确定是哪种类型引起的泄露,其实可以dump两次,然后通过比较两次对象的不同,更加明显看出是那个类型的对象出了问题。

    4.找到该对象。

    5.找到该对象的root。

    root都找到了,剩下的问题就都好解决了。。。。 

            

     
     
    分类: WinDBG
    标签: windbgOutOfMemoryDump
  • 相关阅读:
    Lucene.Net 2.3.1开发介绍 —— 二、分词(一)
    控制‘控制台应用程序’的关闭操作
    详解for循环(各种用法)
    敏捷软件开发
    Sql Server的一些知识点
    在SharePoint 2010 中配置Remote Blob Storage FILESTREAM Provider
    使用LotusScript操作Lotus Notes RTF域
    JOpt Simple 4.5 发布,命令行解析器
    John the Ripper 1.8.0 发布,密码破解工具
    PacketFence ZEN 4.0.1 发布,网络接入控制
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2608776.html
Copyright © 2011-2022 走看看