Out Of Memory的分析及诊断方法
首先 什么是Out Of Memory?就是内存溢出 简称OOM(下边我就用这个简称了啊!) 说白了 就是程序想用内存的时候 OS没有那么多内存可以分配了 然后就抱OOM错误了
首先介绍一下我这个项目的情况 基于exchange +sp +hmc+web service call 通过一个winform的模拟测试程序 单线程添加信息 循环 万次 每循环一次创建一个公司 开通邮件域名 并创建 个帐号 每个帐号都开通邮件服务 现在循环到 次左右的时候 w wp exe的内存占用为private bytes M virtual bytes M 听兄弟讲 他们做过类似的测试 当循环到 个的时候 会出现OOM的问题
既然是OOM 我们当然要介绍一个超级cool的工具 debugdiag!(这个工具以后再介绍 因为要贴N多图 实在痛苦……)通过debugdiag抓memory leak的dump( M) 发现有如下问题 mscorwks泄漏了 M左右的内存
现在转到windbg中来 我们首先看命令!eeheap 它一共有两个参数
> !help eeheap
!EEHeap [ gc] [ loader]
首先看一下 gc的参数 !eeheap gc 这个命令表明 我们程序占用托管堆的大小
> !eeheap gc
Number of GC Heaps
generation starts at x ff f
generation starts at x f df c
generation starts at x c
ephemeral segment allocation context ( x bcbf x bd c)
segment begin allocated size
ead a c c a d x edc( )
e a d a f b x f b ( )
c c bd c x fc c( )
Large object heap starts at x c
segment begin allocated size
c c cfbbd x abd ( )
Total Size xa d ( )
GC Heap Size xa d ( )
dump大小为 M 托管堆大小为 M不到 差别很大的!剩下的内存在哪里?现在来看一个新的命令 !address 运行后 会有一坨又一坨的输出 我们关心的是后面的summary 如下
Usage SUMMARY
TotSize ( KB) Pct(Tots) Pct(Busy) Usage
b ( ) % % RegionUsageIsVAD
c b ( ) % % RegionUsageFree
d ( ) % % RegionUsageImage
fc ( ) % % RegionUsageStack
( ) % % RegionUsageTeb
( ) % % RegionUsageHeap
( ) % % RegionUsagePageHeap
( ) % % RegionUsagePeb
( ) % % RegionUsageProcessParametrs
( ) % % RegionUsageEnvironmentBlock
Tot fff ( KB) Busy b c ( KB)
Type SUMMARY
TotSize ( KB) Pct(Tots) Usage
c b ( ) % <free>
c ( ) % MEM_IMAGE
a ( ) % MEM_MAPPED
a d ( ) % MEM_PRIVATE
State SUMMARY
TotSize ( KB) Pct(Tots) Usage
ee ( ) % MEM_MIT
c b ( ) % MEM_FREE
ca ( ) % MEM_RESERVE
上面的信息比较有意思 RegionUsageImage代表的是dlls占用的内存 一共是 M RegionUsageheap 代表的是NT heaps 一共是 M MEM_MIT和MEM_RESERVE加起来 是virtual memory 他俩的合计是 M 我们还少看了什么?!eeheap还有一个参数 是 loader 运行一下后 会有N长的结果 我们看一部分
!eeheap –loader
Domain fbd
LowFrequencyHeap ba ( ) d ( ) ee ( ) b ( ) ea ( ) f ( f ) ( ) 很黄很暴力…… edc ( ) ee ( ) Size x ce ( )bytes
Wasted x ( )bytes
HighFrequencyHeap ba ( ) e ( f ) aa ( ) c ( f ) ( ) ( ) d ( ) 很黄很暴力 eba ( ) ee ( ) Size x a ( )bytes
Wasted x ( )bytes
StubHeap baa ( ) Size x ( )bytes
Virtual Call Stub Heap
IndcellHeap Size x ( )bytes
LookupHeap Size x ( )bytes
ResolveHeap Size x ( )bytes
DispatchHeap Size x ( )bytes
CacheEntryHeap bc ( ) Size x ( )bytes
Total size x c ( )bytes
一共占用了 M内存 继续看下面的内容 我居然发现了 个module!!!
Module Thunk heaps
Module aa Size x ( )bytes
Module e Size x ( )bytes
Module a Size x ( )bytes
Module Size x ( )bytes
=============很黄很暴力======================
Module ee Size x ( )bytes
Module ee Size x ( )bytes
Module ee c Size x ( )bytes
Module ee c Size x ( )bytes
Total size x ( )bytes
Total LoaderHeap size x a f ( )bytes
=======================================
问题基本出来了 居然在内存里面有将近 万个module!随便dump出来一个 看看 这里又有一个命令 !dumpmodule
随便dump出来一个看 类似如下信息
> !dumpmodule ee
Name qrt x cw Version= Culture=neutral PublicKeyToken=null
Attributes PEFile
Assembly cf e
LoaderHeap
TypeDefToMethodTableMap edcc
TypeRefToMethodTableMap edcc c
MethodDefToDescMap edcc c
FieldDefToDescMap edcc
MemberRefToDescMap edcc c
FileReferencesMap edcc
AssemblyReferencesMap edcc
MetaData start address ed ( bytes)
这里可能看不到啥 那么我们加一个参数 mt来看看
> !dumpmodule mt ee
Name qrt x cw Version= Culture=neutral PublicKeyToken=null
Attributes PEFile
Assembly cf e
LoaderHeap
TypeDefToMethodTableMap edcc
TypeRefToMethodTableMap edcc c
MethodDefToDescMap edcc c
FieldDefToDescMap edcc
MemberRefToDescMap edcc c
FileReferencesMap edcc
AssemblyReferencesMap edcc
MetaData start address ed ( bytes)
Types defined in this module
MT TypeDef Name
ee c x Microsoft Xml Serialization GeneratedAssembly XmlSerializationReaderCreateUserResponseData
ee c x Microsoft Xml Serialization GeneratedAssembly XmlSerializerContract
Types referenced in this module
MT TypeRef Name
e eac x System Xml Serialization XmlSerializationReader
e b x System Xml Serialization XmlSerializerImplementation
e b c x Microsoft Provisioning WebServices HostedActiveDirectory CreateUserResponseData
e be x System Xml XmlReader
fd cc x System Collections Hashtable
f a x e System Object
e c x System Xml XmlQualifiedName
c x System Boolean
e a b x System Xml XmlNameTable
出现了System Xml Serialization 大家熟悉吗?我们转过头来看debugdiag分析的call stack
Call stack sample
Address x c
Allocation Time since tracking started
Allocation Size Bytes
Function Source Destination
mscorjit!norls_allocator nraAllocNewPage+
mscorjit!norls_allocator nraAlloc+ mscorjit!norls_allocator nraAllocNewPage
mscorjit!jitNativeCode+ mscorjit!norls_allocator nraAlloc
mscorjit!CILJit pileMethod+ d mscorjit!jitNativeCode
x E C E
mscorjit!Compiler impExpandInline+ aa
mscorjit!Compiler fgMorphTree+
mscorjit!Compiler fgMorphStmts+ mscorjit!Compiler fgMorphTree
mscorjit!Compiler fgMorphBlocks+ mscorjit!Compiler fgMorphStmts
mscorjit!Compiler fgMorph+ mscorjit!Compiler fgMorphBlocks
mscorjit!Compiler pCompile+ f mscorjit!Compiler fgMorph
mscorjit!Compiler pCompile+ d mscorjit!Compiler pCompile
mscorjit!jitNativeCode+b mscorjit!Compiler pCompile
mscorjit!CILJit pileMethod+ d mscorjit!jitNativeCode
x EED FF
System Xml Serialization TempAssembly InvokeReader(System Xml Serialization XmlMapping System Xml XmlReader System Xml Serialization XmlDeserializationEvents System String)
System Xml Serialization TempAssembly InvokeReader(System Xml Serialization XmlMapping System Xml XmlReader System Xml Serialization XmlDeserializationEvents System String)
System Xml Serialization XmlSerializer Deserialize(System Xml XmlReader System String System Xml Serialization XmlDeserializationEvents) System Xml Serialization TempAssembly InvokeReader(System Xml Serialization XmlMapping System Xml XmlReader System Xml Serialization XmlDeserializationEvents System String)
System Xml Serialization XmlSerializer Deserialize(System Xml XmlReader System String) System Xml Serialization XmlSerializer Deserialize(System Xml XmlReader System String System Xml Serialization XmlDeserializationEvents)
System Xml Serialization XmlSerializer Deserialize(System IO Stream) System Xml Serialization XmlSerializer Deserialize(System Xml XmlReader System String)
Microsoft Provisioning Sdk Xml Serialization ProvisioningObjectFactory Convert[[System __Canon mscorlib] [System __Canon mscorlib]](System __Canon) System Xml Serialization XmlSerializer Deserialize(System IO Stream)
Microsoft Provisioning WebServices ServiceBase Submit[[System __Canon mscorlib] [System __Canon mscorlib]](System __Canon System String System String Boolean) Microsoft Provisioning Sdk Xml Serialization ProvisioningObjectFactory Convert[[System __Canon mscorlib] [System __Canon mscorlib]](System __Canon)
Microsoft Provisioning WebServices HostedActiveDirectory Service CreateOrganization(Microsoft Provisioning WebServices HostedActiveDirectory CreateOrganizationRequest Boolean)
x E BE B
x A E E
System Web Services Protocols LogicalMethodInfo Invoke(System Object System Object[])
System Web Services Protocols WebServiceHandler Invoke() System Web Services Protocols LogicalMethodInfo Invoke(System Object System Object[])
x F FC
System Threading _TimerCallback TimerCallback_Context(System Object)
System Threading ExecutionContext Run(System Threading ExecutionContext System Threading ContextCallback System Object)
webengine!HashtableIUnknown AddCallback+a
webengine!HttpCompletion ProcessRequestInManagedCode+ a
webengine!HttpCompletion ProcessRequestInManagedCode+ a
webengine!HttpCompletion ProcessCompletion+ e webengine!HttpCompletion ProcessRequestInManagedCode
webengine!CorThreadPoolWorkitemCallback+
x F
x F BC
kernel !BaseThreadStart+
看到这里 基本差不多 偶认为是exchange 内部的代码问题 此话怎讲?从头说 在System Xml Serialization下面 有一个by design的 bug 我们用reflector看XmlSerializer的构造代码
this tempAssembly = cache[defaultNamespace type]
if (this tempAssembly == null)
{
lock (cache)
{
this tempAssembly = cache[defaultNamespace type]
if (this tempAssembly == null)
{
XmlSerializerImplementation implementation
Assembly assembly = TempAssembly LoadGeneratedAssembly(type defaultNamespace out implementation)
if (assembly == null)
{
this mapping = new XmlReflectionImporter(defaultNamespace) ImportTypeMapping(type null defaultNamespace)
this tempAssembly = GenerateTempAssembly(this mapping type defaultNamespace)
}
else
{
this mapping = XmlReflectionImporter GetTopLevelMapping(type defaultNamespace)
this tempAssembly = new TempAssembly(new XmlMapping[] { this mapping } assembly implementation)
}
}
cache Add(defaultNamespace type this tempAssembly)
}
为了加快运行速度 xmlserializer做了cache 在代码中 也许我们有N多的type 那么每个type在这里都做了一个assembly 都把assembly放到了cache中 这样 本来没问题 但是如果type有几千个 有几万个 那么就有几千几万个temp assembly出现 这些assembly都很小 也许只有 个字节 也许是 字节 但是注意的是 内存分配时 是按照 块 来分配的 假如说每个块最小为 k大小 那么即使只分配一个字节的内存 我们也要申请一个 k的page 那么 如果我们的小块非常非常多 那么我们身子缩小N倍后 你会发现内存里面四处都是小窟窿 这些窟窿加起来很大 但是别人就是不能用 因为这 k内存 必须要连续的块
so 当我们发现w wp exe仅仅 百兆的时候 就报OOM了 就是这个原因
lishixinzhi/Article/program/net/201311/12615
谭弦知甘: OutOfMemory(内存溢出)是一个程序员常见的错误类型. 解决办法:1、首先先确定是不是开启的程序太多,导致内存不足.我们可以打开任务管理器,把占用内存过多的应用关闭.或者直接重启电脑试试.2、试试加大虚拟内存(开启之前,看看游戏是否有最新版本,加大虚拟内存,会对系统带来一定影响),操作流程:这台电脑→属性→高级→性能设置→高级→虚拟内存更改.设置最小和最大为你的电脑内存的1.5到2倍就行了.3、如果还是不行,可以尝试一下dos命令来解决下,点击开始-运行,输入cmd.然后在输入命令:Bcdedit /set IncreaseUserVa 3072,完成之后,按Entel(回车)键确定即可.
承德县17648838637: 开机时出现Out of memory是什么意思? - ?
谭弦知甘: 是内存不足的意思,大概是你开的东西太多了,对于Windows中的内存不足的处理方法可参考如下资料: 如果在运行Windows应用程序时,出现“内存不足”的故障,可按下列方法进行检查和处理: 1、首先应检查Windows的资源使用情况,...
承德县17648838637: linux出现out of memory是什么问题 - ?
谭弦知甘: Linux出现out of memory就是新启动的程序运行所需要的内存,大于系统空闲的物理内存容量,Linux系统一般会直接对这个程序进行kill从而不让程序启动,如果无法加大物理内存(一般也不会因为偶尔的情况就去加大内存),可以尝试增加swap内存交换分区,swap分区相当于Windows系统里面的“虚拟内存”设置.
承德县17648838637: 如何定位OutOfMemory的根本原因 - ?
谭弦知甘: 分析工具1) 动态分析工具 jprofile2) 静态分析工具 a: 在启动java的时候加上参数-xx:+heapdumponoutofmemoryerror,这样如果由于oom导致jvm crash的时候可以便于我们分析,生成的heap dump文件名字的命名规范如下, java_pidxxxx.hprof ...
承德县17648838637: 运行软件出现out of memory - ?
谭弦知甘: out of memory的意思是内存不足,这里的内存指的是RAM不足,有可能是你同时运行了很多个程序,或是你的内存条容量很小,我的电脑右键——属性——常规选项,看右下角就知道你的内存是多少
承德县17648838637: xp系统玩cf弹出“out of memory”是为什么? - ?
谭弦知甘: out of memory是提醒你游戏的缓存记录丢失了,可能是因为系统升级的原因.一、out of memory是什么意思 out of memory英文意思是电脑内存不足,我们都清楚,电脑程序的运行不仅仅对电脑CPU进行消耗,同时对内存也会进行占用,当占用...
承德县17648838637: 电脑出现out of memory 是什么问题??
谭弦知甘: 可能是电脑的虚拟内存太小引起OUT OF MEMORY. 解决方法:右击我的电脑,高级→性能 设置→高级,更改虚拟内存-设置的数值一般为你的电脑内存的1倍较好
承德县17648838637: outofmemory是什么意思 - ?
谭弦知甘: OutOfMemory(内存溢出)是一个程序员常见的错误类型
承德县17648838637: 电脑出现out of memory 是什么问题` - ?
谭弦知甘: 这是因为你的电脑内存不足引起的,试一下加大虚拟内存 方法为右击我的电脑-高级-性能 设置-高级-更改虚拟内存-设置D盘最小和最大为你的电脑内存的1.5到2倍就行了 求采纳
承德县17648838637: Java OutOfMemoryError 的原因是什么,什么是Java native方法 - ?
谭弦知甘: OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存.说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域...