有一个超出内存使用量(OutOfMemory)的异常,我该如何解决
有一个超出内存使用量(OutOfMemory)的异常,我该如何解决
问题:
有一个ASP.NET 的应用程序,经常性地会报内存不足的错误。OutOfMemoryExceptions。
原因:
让我们来找找……
解决方法:
使用WinDbg来看看一个堆。
确实有泄漏么?
使用性能监视器来看看你的应用的内存事情情况,如果内存是在慢慢的增加,但从不减少,那么你有泄漏问题。如果它增长上去,降下来的时候像一个陡峭的峰,那你肯定是某个特定的操作使用了一大块的内存,然后被垃圾回收了。
如何才能确诊这些?
下面我会一步一步地带你来查找。
1) 得到一个dump文件。
这个使用WinDbg和Adplus,如果你没有安装WinDbg,那先看看我前面的文章。
2) 打开dump文件,加载SOS
在WinDbg中打开dump文件,加载SOS扩展
.load [path]\sos |
3) 运行 dumpheap,运行下面的命令
!dumpheap -stat |
它会显示在堆(heap)上的对象的统计信息,包含四列的摘要信息。
对象的Method Table 信息。
这类型对象的数量。
这类对象的总大小(字节为单位)。
对象类型的名字。
当心,不要忽视 –stat 这个参数,否则WinDbg会dump出在整个堆上的每一个对象的地址,那你的屏幕上会有很多的信息。
4) 分析dumpheap出来的信息,下面是一部分输出:
0:000> !dumpheap -stat Statistics: MT Count TotalSize Class Name System.Net.DefaultCertPolicy System.Diagnostics.TraceListenerCollection ........CONTINUED......... 790fa3e0 1,431,594 122,806,484 System.String Total 10,389,625 objects, Total size: 463,313,540 |
在这个dump中,有1,431,594个字符串,总大小是122MB,879,515个对象,大小是43MB。
在堆中的对象会比我们看到的要大
那个TotalSize列不是100%正确的。看LiteralControls 这个行,他们仅仅使用了
使用 !dumpobj
让我们走进看看System.Web.UI.LiteralControls 这个对象,我们使用
!dumpheap -type System.Web.UI.LiteralControl,在屏幕被太多信息填充前,快速的按下CTRL+Break来中断。
0:000> !dumpheap -type System.Web.UI.LiteralControl 023ea 023eab ........CONTINUED........ 023fe 023fe414 |
你可以看到每个LiteralControl 对象是 60B的大小。和我前面说的一样,这只是代表对象的结构大小,并不包含引用的对象和属性。我们现在找一个地址,然后执行!dumpobject(简写:!do),下面是输出:
0:000> !do 023ea Name: System.Web.UI.LiteralControl MethodTable: EEClass: Size: 60(0x GC Generation: 2 (C:\WINDOWS\assembly\GAC_32\System.Web\ Fields: MT Field Offset 790fa3e0 4001fe0 4 System.String 0 instance 00000000 _id …… 790fa3e0 4002211 34 System.String 0 instance 02238664 _text |
现在,找几个来看看,看看那些文本属性的值,那个最后面的在底部的,地址是02238664 的,拿来看看,很简单,使用 !do +adress
0:000> !do 02238664 Name: System.String MethodTable: 790fa3e0 EEClass: 790fa340 Size: 158(0x9e) bytes GC Generation: 2 (C:\WINDOWS\assembly\GAC_32\mscorlib\ String: </td> </tr> </table> <!-- end of content table -->
Fields: MT Field Offset 790fed |
我们也可以检查这个对象中的其他属性,只要我们愿意这么做。但,另外有一个命令非常的有用。
使用 !objsize
有什么命令可以得到System.Web.UI.LiteralControl的大小么?非常简单,使用 !objsize ,这个命令查看所有的有这个对象的指针,然后计算它们的大小。运行 !help objsize 可以看到帮助信息。
在堆中的对象也可能比看起来的小
我们在LiteralControl 对象上运行 !objsize 看看,结果非常有趣,命令好像很忙碌的样子,花费很长的时间,我们得到了“事实上”的结果:
0:000> !objsize 023ea sizeof(023ea |
456MB,这怎么可能?我们回上去看看我们运行 !do LiteralControl 命令的地方,我们可以看到,这个控件有一个对page 的引用。这个page又对cache有引用,不久后,有了对整个堆的引用。这种重复的引用而导致的大小计算是不正确的。
总结:
希望这里能给你足够多的帮助,我们很快速的看了三个相关的简单命令,他们是:
!dumpheap
!dumpobj
!objsize
原文地址:[url]http://www.sula.cn/90.shtml[/url]