捉虫记(一)GC堆中的“内存泄漏”

开发 开发工具
首先介绍一下程序,Server程序,同时有好多Client连接,Client用tcpSocket发送数据给Server,Server对数据进行处理并返回处理结果给Client。

首先介绍一下程序,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中,然后开启另外的线程来处理,可惜处理线程被谁注释掉了(跟踪功能因为没啥用处,被去掉了,但是去掉了应该不让入队啊),好吧,赶紧修改代码,重新部署......

原文链接:http://www.cnblogs.com/StevenChennet/archive/2012/07/24/2606780.html

【编辑推荐】

责任编辑:张伟 来源: StevenChennet的博客
相关推荐

2012-08-16 10:43:10

GC

2021-08-19 09:50:53

Java内存泄漏

2020-08-27 21:36:50

JVM内存泄漏

2022-02-08 17:17:27

内存泄漏排查

2022-09-13 17:46:19

STA模式内存

2021-11-02 07:54:41

内存.NET 系统

2011-06-16 09:28:02

C++内存泄漏

2022-05-26 09:51:50

JavaScrip内存泄漏

2021-05-13 08:51:20

GC问题排查

2022-06-15 16:04:13

Java编程语言

2024-01-30 10:12:00

Java内存泄漏

2009-06-03 15:52:34

堆内存栈内存Java内存分配

2020-08-17 17:47:30

内存技术测试

2015-03-30 11:18:50

内存管理Android

2017-03-20 13:43:51

Node.js内存泄漏

2017-03-19 16:40:28

漏洞Node.js内存泄漏

2020-01-03 16:04:10

Node.js内存泄漏

2019-01-30 18:24:14

Java内存泄漏编程语言

2016-08-22 08:36:14

ReactiveCoc内存泄漏GitHub

2014-01-14 09:10:53

GoHTTP内存泄漏
点赞
收藏

51CTO技术栈公众号