如何处理OutOfMemoryException异常

原文出自:http://blogs.msdn.com/johan/archive/2007/01/11/i-am-getting-outofmemoryexceptions-how-can-i-troubleshoot-this.aspx
版权归原作者所有,转载请注明出处

如何处理OutOfMemoryException异常

问题:
asp.net应用程序出现OutOfMemoryException异常

解决方案:
使用Windbg查看托管堆


是内存泄漏引起的么?
使用perfmon查看应用程序的内存使用情况.如果内存缓慢上升且从未释放,说明有内存泄漏.如果向过山车一样起起伏伏,基本上是某种操作使用了大量的内存稍后又被垃圾搜集

如何排除故障?
下面一步步描述如何解决此类问题


1.获得内存转储文件

2.打开转储文件然后加载SOS
用windbg打开转储文件然后加载SOS扩展.可以在框架目录下找到,.net2.0下是C:/Windows/Microsoft.NET/Framework/v2.0.50727 ,使用以下命令加载扩展

.load [path]/sos

3.运行dumpheap
运行以下的命令:

!dumpheap -stat

将用四列来显示堆内对象的统计信息

The method table of the object //对象的方法表
The number of objects of this type on the heap //堆上该类型对象的数量
The total size of these objects in bytes  //这些对象的总计大小,单位为byte
The name of the object type  //对象类型的名称

当心,不要忽略 -stat参数.如果漏掉了此参数,windgb将显示堆上每一个对象的地址。

分析!dumpheap命令提供的信息
下面是例子

0:000> !dumpheap -stat
Statistics:
MT             Count          TotalSize                        Class Name
7a787cc4           1              12                      System.IO.FileSystemWatcher+FSWAsyncResult
7a75904c           1              12                      System.Diagnostics.OrdinalCaseInsensitiveComparer
7a7575cc           1              12                      System.CodeDom.Compiler.CodeDomConfigurationHandler
7a7571a8           1              12                      System.Net.DefaultCertPolicy
7a75661c           1              12                      System.Diagnostics.TraceListenerCollection
7a755834           1              12                      System.Diagnostics.PerformanceCounterCategoryType
........CONTINUED.........
68a66a88     227,559      12,743,304        System.Web.UI.WebControls.Literal
68a2f7fc     399,272      14,373,792           System.Web.UI.ControlCollection
68a92e2c     768,731      33,824,164        System.Web.UI.Control+OccasionalFields
68a884a0     641,952      38,517,120        System.Web.UI.LiteralControl
79124228     879,515      43,394,976       System.Object[]
790fa3e0   1,431,594     122,806,484      System.String

Total 10,389,625 objects, Total size: 463,313,540

在这个dump中,有1,431,594个string总计122M,879,515object总计43M,等等.

堆上的object可能会比显示的要大
TotalSize 栏显示的数据并不是100%正确。看看上面位于倒数第三行的LiteralControls 。仅占用了38M,真的只有这么多?TotalSize 指的是对象结构的大小,成员变量如string,integer以及其他子对象并不包含在内。这一列的数据是象征性的,真实数据可能比现实的大得多。 LiteralControl 对象包含不少子对象,其中三个是string,他们的大小在System.String中列出。


使用!dumpobj
让我们仔细看看System.Web.UI.LiteralControls.使用!dumpheap -type System.Web.UI.LiteralControls命令,然后在显示太多行之前快速按下Ctrl+Break

0:000> !dumpheap -type System.Web.UI.LiteralControl
 Address       MT Size Gen
023ea0a8 68a884a0   60   2 System.Web.UI.LiteralControl
023ea0e4 68a884a0   60   2 System.Web.UI.LiteralControl
023ea374 68a884a0   60   2 System.Web.UI.LiteralControl
023ea460 68a884a0   60   2 System.Web.UI.LiteralControl
023ea510 68a884a0   60   2 System.Web.UI.LiteralControl
023eab3c 68a884a0   60   2 System.Web.UI.LiteralControl
........CONTINUED........
023fe31c 68a884a0   60   2 System.Web.UI.LiteralControl
023fe414 68a884a0   60   2 System.Web.UI.LiteralControl
023fe4c4 68a884a0   60   2 System.Web.UI.LiteralControl
023fe500 68a884a0   60   2 System.Web.UI.LiteralControl


看起来每个LiteralControl大小为60 byte.不过这仅仅是对象结构的大小,不是它所引用的对象和属性的大小.挑一个LiteralControl的地址来执行!dumpobj命令(简写为!do).结果如下:

0:000> !do 023ea0a8
Name: System.Web.UI.LiteralControl
MethodTable: 68a884a0
EEClass: 68a88428
Size: 60(0x3c) bytes
GC Generation: 2
(C:/WINDOWS/assembly/GAC_32/System.Web/2.0.0.0__b03f5f7f11d50a3a/System.Web.dll)
Fields:
      MT    Field Offset                   Type   VT     Attr    Value Name
790fa3e0  4001fe0      4          System.String    0 instance 00000000 _id
790fa3e0  4001fe1      8          System.String    0 instance 00000000 _cachedUniqueID
68a2af44  4001fe2      c   ...em.Web.UI.Control    0 instance 023e8864 _parent
68a91070  4001fe3     2c           System.Int32    0 instance        0 _controlState
68a85ea0  4001fe4     10   ...m.Web.UI.StateBag    0 instance 00000000 _viewState
68a2af44  4001fe5     14   ...em.Web.UI.Control    0 instance 023e8864 _namingContainer
68a273d0  4001fe6     18     System.Web.UI.Page    0 instance 01df4514 _page
68a92e2c  4001fe7     1c   ...+OccasionalFields    0 instance 00000000 _occasionalFields
68a2b378  4001fe8     20   ...I.TemplateControl    0 instance 00000000 _templateControl
68a14528  4001fe9     24   ...m.Web.VirtualPath    0 instance 00000000 _templateSourceVirtualDirectory
68a8bb48  4001fea     28   ...rs.ControlAdapter    0 instance 00000000 _adapter
68a3a8f8  4001feb     30   ...SimpleBitVector32    1 instance 023ea0d8 flags
790f9c18  4001fda    c70          System.Object    0   shared   static EventDataBinding
>> Domain:Value 000f0d00:NotInit 0011a720:01df0028 <<
790f9c18  4001fdb    c74          System.Object    0   shared   static EventInit
>> Domain:Value 000f0d00:NotInit 0011a720:01df0034 <<
790f9c18  4001fdc    c78          System.Object    0   shared   static EventLoad
>> Domain:Value 000f0d00:NotInit 0011a720:01df0040 <<
790f9c18  4001fdd    c7c          System.Object    0   shared   static EventUnload
>> Domain:Value 000f0d00:NotInit 0011a720:01df004c <<
790f9c18  4001fde    c80          System.Object    0   shared   static EventPreRender
>> Domain:Value 000f0d00:NotInit 0011a720:01df0058 <<
790f9c18  4001fdf    c84          System.Object    0   shared   static EventDisposed
>> Domain:Value 000f0d00:NotInit 0011a720:01df0064 <<
79124228  4001fec    c88        System.Object[]    0   shared   static automaticIDs
>> Domain:Value 000f0d00:NotInit 0011a720:01df0070 <<
790fa3e0  4002211     34          System.String    0 instance 02238664 _text

用!do来查看text属性.

0:000> !do 02238664
Name: System.String
MethodTable: 790fa3e0
EEClass: 790fa340
Size: 158(0x9e) bytes
GC Generation: 2
(C:/WINDOWS/assembly/GAC_32/mscorlib/2.0.0.0__b77a5c561934e089/mscorlib.dll)
String:      </td>
    </tr>
  </table>
<!-- end of content table -->
 
Fields:
MT Field Offset Type VT Attr Value Name
790fed1c 4000096 4 System.Int32 0 instance 71 m_arrayLength
790fed1c 4000097 8 System.Int32 0 instance 70 m_stringLength
790fbefc 4000098 c System.Char 0 instance 3c m_firstChar
790fa3e0 4000099 10 System.String 0 shared static Empty
>> Domain:Value 000f0d00:790d6584 0011a720:790d6584 <<
79124670 400009a 14 System.Char[] 0 shared static WhitespaceChars
>> Domain:Value 000f0d00:01d413b8 0011a720:01d44f80 <<


可以看到,这个字符串包括闭合table的数据.也可以查看其他希望查看的属性,但这儿有一个非常有用的命令:

使用!objsize
有办法查看System.Web.UI.LiteralControl的总大小么?-非常简单!用!objsize命令.!objsize命令计算一个对象内部所有指针的大小.下面是!objsize命令的内部文档说明:

0:000> !help objsize
-------------------------------------------------------------------------------
!ObjSize [<对象地址>]
 
如果不指定参数,!ObjSize命令列出托管线程上所有的对象大小.同时枚举出进程内所有 GCHandle,并且合计出这些handle指向的所有对象的大小.在计算对象大小的时候,!ObjSize将所有子对象的大小加到父对象上

 
举个例子, !DumpObj 列出了Customer对象的大小为20字节
 
0:000> !do a79d40
Name: Customer
MethodTable: 009038ec
EEClass: 03ee1b84
Size: 20(0x14) bytes
(C:/pub/unittest.exe)
Fields:
MT         Field Offset  Type              Attr    Value  Name
009038ec 4000008      4 CLASS          instance 00a79ce4  name
009038ec 4000009      8 CLASS          instance 00a79d2c  bank
009038ec 400000a      c System.Boolean instance        1 valid
 
but !ObjSize lists 152 bytes:
0:000> !ObjSize a79d40
sizeof(00a79d40) = 152 ( 0x98) bytes (Customer)
 
 但!ObjSize显示为152字节
 
这是因为一个Customer对象引用了一个Bank对象, 有一个name属性,Bank对象引用一个Address字符串.可以使用!ObjSize来确定任何特定对象,比如web server上的托管缓存

堆上的对象的大小可能比显示出来的小
那么如果我们使用!objsize来查看LiteralControl会得到什么?非常有趣,因为会发生的是;调试器会忙碌相当一段时间,最后得到以下的结果:

0:000> !objsize 023ea0a8
sizeof(023ea0a8) = 456918136 ( 0x1b3c0478) bytes (System.Web.UI.LiteralControl)

456M!这怎么可能?如果回头看看用!do命令查看LiteralControl的地方,将看到这个控件拥有对page的引用,page有对cache的引用,这样将得到几乎对整个堆的引用


摘要
期望此文能让你对sos扩展提供的三个简单命令能做些什么有快速的大概了解,这些命令是:

!dumpheap
!dumpobj
!objsize
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值