Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap
摘要 :
NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex.
!wheap 这个命令可以用于打印出heap structure信息. heap 上 object汇总后的信息. 这个命令也可以按照一些条件过滤出objects, 不过执行速度比较慢. 在这一点上, 更推荐!windex.
!windex是一个非常常用的命令. 这个命令可以用来查找heap上面实现某个interface, 继承某个abstract class 或者class的对象. 这个命令执行之后, 也会缓存做过index后的对象, 可以加快类似命令的之行速度. 同时也有非常酷炫的功能, 可以批量的从同一类型的object中显示出个别字段.
!wheap
!wheap 这个命令可以用于打印出heap structure信息. 以及heap object的汇总后的信息. 加上参数 –detailsonly, 正如他的名字一样, 可以打印出详细的信息.
它可以显示出的Heap的数量, 由于这个CLR RUTIME使用的GC Mode是Server Mode (1). 那么Heap的数量会根据Processor的数量有所不同. 这里能够看到Heap的数量是2个.
关于GC 类型的区别, 可以参考下面的链接
- http://blogs.msdn.com/b/clyon/archive/2004/09/08/226981.aspx
- https://msdn.microsoft.com/en-us/library/cc165011(v=office.11).aspx
- http://blogs.msdn.com/b/clyon/archive/2005/02/04/367419.aspx
从输出结果可以看出来每个Managed Heap都有自己的一段地址. 如果Heap的size比较大, 还会包含多个Segment. 每个Segment的最大值都是固定的. 最大值值由很多因素决定. 不同的环境和配置时, 这个值会不一样. 当一个Segment将要分配满的时候, 会创建出一个新的Segment. 这个Segment 会缓慢增长, 直到长满为止.
这个命令也会提示GC Heap 上不同Generation代上的object的数量. 比较特别的是 Generation 3. 我们所认识的Generation 3.
0:000> !wheap -detailsonly
Heaps: 2 <-- heap 的数量 -->
Server Mode: 1 <-- GC Mode, 1表示是Server Mode -->
Heap [0]: <-- 第一个Heap -->
Allocated: 0000000155a56fe8
Card Table: 00000000027ea6b0
Ephemeral Heap Segment: 0000000155660000
Finalization Fill Pointers: 000000c28007cd40
Heap Address: 0000000000e1e790
Lowest Address: 0000000155660000
Highest Address: 00000001f5660000
Generation Addresses:
[0]:AllocStart(0000000155793728),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
[1]:AllocStart(0000000155660080),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
[2]:AllocStart(0000000155660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
[3]:AllocStart(00000001d5660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(00000001d5660000) Segments:
Segment: 0000000155660000 Start: 0000000155660068 End: 0000000155981340 HiMark: 0000000155a56fe8 Committed: 0000000155a61000 Reserved: 0000000195660000 Next: 0000000000000000 <-- 第一个Segment, 由于有第二个Segment已经创建出来, 可以猜测这个Segment已经快分配完. 用End的地址减去Start的地址能够算出一个Segment的大小. 这里是64MB. -->
Segment: 00000001d5660000 Start: 00000001d5660068 End: 00000001d569bf10 HiMark: 00000001d569bf10 Committed: 00000001d56a1000 Reserved: 00000001e5660000 Next: 0000000000000000
Heap [1]:
Allocated: 0000000195907af8
Card Table: 00000000027ea6b0
Ephemeral Heap Segment: 0000000195660000
Finalization Fill Pointers: 000000c28007cd40
Heap Address: 0000000000e20db0
Lowest Address: 0000000155660000
Highest Address: 00000001f5660000
Generation Addresses:
[0]:AllocStart(000000019573e270),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
[1]:AllocStart(0000000195660080),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
[2]:AllocStart(0000000195660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
[3]:AllocStart(00000001e5660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(00000001e5660000) Segments:
Segment: 0000000195660000 Start: 0000000195660068 End: 0000000195907af8 HiMark: 0000000195907af8 Committed: 0000000195911000 Reserved: 00000001d5660000 Next: 0000000000000000
Segment: 00000001e5660000 Start: 00000001e5660068 End: 00000001e5660080 HiMark: 00000001e5660080 Committed: 00000001e5661000 Reserved: 00000001f5660000 Next: 0000000000000000 Heap Areas:
Area [0000000155660068]: 0000000155660068-0000000155660080 ( 24) Heap: 0 Generation: 2 Large: 0 <-- 表示 24个对象处于Generation 2 -->
Area [0000000155660080]: 0000000155660080-0000000155793728 ( 1259176) Heap: 0 Generation: 1 Large: 0
Area [0000000155793728]: 0000000155793728-0000000155a61000 ( 2939096) Heap: 0 Generation: 0 Large: 0
Area [0000000195660068]: 0000000195660068-0000000195660080 ( 24) Heap: 1 Generation: 2 Large: 0
Area [0000000195660080]: 0000000195660080-000000019573e270 ( 909808) Heap: 1 Generation: 1 Large: 0
Area [000000019573e270]: 000000019573e270-0000000195911000 ( 1912208) Heap: 1 Generation: 0 Large: 0
Area [00000001d5660068]: 00000001d5660068-00000001d569bf10 ( 245416) Heap: 0 Generation: 3 Large: 1 <-- 表示 245416个对象处于Generation 3, 即Large Object Heap -->
Area [00000001e5660068]: 00000001e5660068-00000001e5660080 ( 24) Heap: 1 Generation: 3 Large: 1
0000000155660068 0000000000e111d0 24 0 2 Free
0000000155660080 0000000000e111d0 24 0 1 Free
0000000155660098 0000000000e111d0 24 0 1 Free
00000001556600b0 000007fef0b96cb8 160 0 1 System.Exception
0000000155660150 000007fef0b96f10 160 0 1 System.OutOfMemoryException
00000001556601f0 000007fef0b96f98 160 0 1 System.StackOverflowException
0000000155660290 000007fef0b97020 160 0 1 System.ExecutionEngineException
0000000155660330 000007fef0b970a8 160 0 1 System.Threading.ThreadAbortException
00000001556603d0 000007fef0b970a8 160 0 1 System.Threading.ThreadAbortException .....
0000000195747da0 000007fee67a1e60 32 1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
0000000195747dc0 000007fee67a1f28 56 1 0 System.Xml.Schema.XmlSchemaObjectTable+XSOEnumerator
0000000195747df8 000007fef0b9c768 36 1 0 System.Int32[]
0000000195747e20 000007fee67a2048 96 1 0 System.Collections.Generic.Dictionary`2+Entry[[System.Xml.XmlQualifiedName, System.Xml],[System.Xml.Schema.XmlSchemaObject, System.Xml]][]
0000000195747e80 000007fee679fd20 88 1 0 System.Xml.Schema.XmlSchemaObjectTable+XmlSchemaObjectEntry[]
0000000195747ed8 000007fee67a1e60 32 1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
00000001d5660068 0000000000e111d0 24 0 3 Free
00000001d5660080 000007fef0b9adf8 8192 0 3 System.Object[]
..... This output was throttled. Only the first 500 objects of each heap range has been shown.
Use -nothrottle to list all objects or any limiting parameter (-type for example)
- detailsonly 的目的是打印出来Heap的structure的信息. Object仅仅打印前500个. 如果要打印出的Heap上所有的对象, 则要使用参数 –nothrottle, 不过这一命令的运行时间会略长.
用-start 以及 –end 参数, 可以打印出一个范围内的object的数据.
用 –mt <string>参数, 可以打印出指定的MethodTable值的objects. 类似于命令!gcheap –mt <addr>
!wheap的显示结果会统计出Heap上Object的一些汇总信息. 这些信息是按照对象类型进行分类, 一条数据表示一个对象类型.
第一列是其中一个object的地址, 如果有多个对象是相同类型, 仅仅显示第一个.
第二列是这个类型的对象的MethodTable的地址.
第三列是这个类型的总共使用了多少virtual memory. 在做high memory 的场景的CASE的情况下, 可以通过这个值快速找到占用virtual memory 最高的对象类型.
第四列是这个类型的数量.
第五列是这个类型的名称
!wheap ……. 0000000195747d18 000007fef0b9c768 36 1 0 System.Int32[]
0000000195747d40 000007fee679a850 96 1 0 System.Collections.Generic.Dictionary`2+Entry[[System.Xml.XmlQualifiedName, System.Xml],[System.Xml.Schema.SchemaAttDef, System.Xml]][]
0000000195747da0 000007fee67a1e60 32 1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
0000000195747dc0 000007fee67a1f28 56 1 0 System.Xml.Schema.XmlSchemaObjectTable+XSOEnumerator
0000000195747df8 000007fef0b9c768 36 1 0 System.Int32[]
0000000195747e20 000007fee67a2048 96 1 0 System.Collections.Generic.Dictionary`2+Entry[[System.Xml.XmlQualifiedName, System.Xml],[System.Xml.Schema.XmlSchemaObject, System.Xml]][]
0000000195747e80 000007fee679fd20 88 1 0 System.Xml.Schema.XmlSchemaObjectTable+XmlSchemaObjectEntry[]
0000000195747ed8 000007fee67a1e60 32 1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
!windex
!windex是一个非常常用的命令. 这个命令不但可以早heap中挖掘你所需要的某个类型的数据. 最有用处的地方是, 可以用来查找heap上面实现某个interface, 继承某个abstract class 或者class的对象. 这个命令执行之后, 也会缓存做过index后的对象, 可以加快类似命令的之行速度.
下面SHOW一下!windex比较有趣的功能, 通过WINDBG的UI将heap上个object展示成树形结构. 这样的做法比较形象的对各种对象进行分析.
首先在windbg中运行!windex -tree的命令. 这个命令会快速对heap上的object做index. 然后生成一个临时文件在本地. 同时也生成了一条命令.
0:000> !windex -tree
Starting indexing at 20:19:06 PM
Indexing finished at 20:19:07 PM
7,098,503 Bytes in 77,156 Objects
Index took 00:00:01
Copy, paste and run command below:
.cmdtree C:\Users\sonicguo\AppData\Local\Temp\HEAE0D6.tmp

将这个命令COPY & PASTE 到命令行上执行. 然后会弹出另外一个窗口, 如下图. 这个图的效果已经非常有点接近Visual Studio中检查object的窗口效果了.

这个时候可以double click 某一条记录. 会显示出该条记录的详情.
0:000> !windex -mt 000007FEE79EFA20
Index is up to date
If you believe it is not, use !windex -flush to force reindex
00000001556ebc68 000007fee79efa20 System.ServiceModel.BasicHttpBinding 112 0 1
00000001556f2b88 000007fee79efa20 System.ServiceModel.BasicHttpBinding 112 0 1
如果双击的不是这个类型, 而是该类型下面某一个field, 那么会显示出所有这个类型的每一个字段的值. 例如这里BasicHttpBinding有两个. 我想知道每一个BasicHttpBinding的name. 那么只要双击这个name, 就会把两个BasicHttpBinding的名字都打印出来.
这个方式非常适合快速调查某一个类型的特定字段的值.

0:000> .foreach({$addr} {!windex -short -mt 000007FEE79EFA20}){.echo Address: {$addr}; !wselect name from {$addr}}
Address: 00000001556ebc68
[System.ServiceModel.BasicHttpBinding]
System.String name = 00000001556ccbd8 wsHttpBindingConfiguration
Address: 00000001556f2b88
[System.ServiceModel.BasicHttpBinding]
System.String name = 00000001556ce118 basicHttpBindingConfigurationJava
!windex 还支持模糊查询. 例如, 执行下面这个命令就可以把所有后缀为BasicHttpBinding的对象都打印出来.
0:000> !windex -type *.BasicHttpBinding
Index is up to date
If you believe it is not, use !windex -flush to force reindex
00000001556ebc68 000007fee79efa20 System.ServiceModel.BasicHttpBinding 112 0 1
00000001556f2b88 000007fee79efa20 System.ServiceModel.BasicHttpBinding 112 0 1
配合 !wfrom 来使用, 可以从过滤出来的对象中找到某一个指定的字段, 前提是要知道字段名称.
0:000> !wfrom -type *.BasicHttpBinding select name
name: wsHttpBindingConfiguration
name: basicHttpBindingConfigurationJava 2 Object(s) listed
这个显示结果虽然很爽, 但是没有能够看到对象的地址, 略微不足. 为了弥补这个不足, 可以使用额外的参数 $addr() 来解决.
0:000> !wfrom -type *.BasicHttpBinding select $addr(),name
calculated: 00000001556EBC68
name: wsHttpBindingConfiguration
calculated: 00000001556F2B88
name: basicHttpBindingConfigurationJava
不仅如此, 还可以用$a()的参数来添加别名, 使得输出结果可读性更强.
0:000> !wfrom -type *.BasicHttpBinding select $a("Address",$addr()), $typename(), name
Address: 00000001556EBC68
calculated: System.ServiceModel.BasicHttpBinding
name: wsHttpBindingConfiguration
Address: 00000001556F2B88
calculated: System.ServiceModel.BasicHttpBinding
name: basicHttpBindingConfigurationJava
2 Object(s) listed
这么多的新功能, 是否觉得酷炫吊炸天呢? 下一期, 我会继续介绍更多酷炫的新功能.
Sonic Guo
Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap的更多相关文章
- Windbg Extension NetExt 使用指南 【1】 ---- NetExt 介绍
摘要 : 在使用WINDBG做debugging的时候,需要一个好的工具帮助进行数据分析. 最常见的extension包括SOS, PSSCOR. NetExt则是另外一种提供了丰富命令功能的deb ...
- Windbg Extension NetExt 使用指南 【2】 ---- NetExt 的基本命令介绍
摘要 : 本章节介绍NetExt常用的命令. 并且对SOS进行一些对比. NetExt的帮助 要想玩好NetExt, 入门就得看帮助. 看NetExt的帮助可以调用!whelp 命令. 这样hi列举出 ...
- Windbg Extension NetExt
Windbg Extension NetExt 摘要 : 在使用WINDBG做debugging的时候,需要一个好的工具帮助进行数据分析. 最常见的extension包括SOS, PSSCOR. N ...
- HotSpot关联规则算法(2)-- 挖掘连续型和离散型数据
本篇代码可在 http://download.csdn.net/detail/fansy1990/8502323下载. 前篇<HotSpot关联规则算法(1)-- 挖掘离散型数据>分析了离 ...
- Node.js权威指南 (5) - 使用Buffer类处理二进制数据
5.1 创建Buffer对象 / 705.2 字符串的长度与缓存区的长度 / 725.3 Buffer对象与字符串对象之间的相互转换 / 74 5.3.1 Buffer对象的toString方法 / ...
- 这个接口管理平台 eoLinker 开源版部署指南你一定不想错过
本文主要内容是讲解如何在本地部署eoLinker开源版. 环境要求 1.PHP 5.5+ / PHP7+(推荐) 2.Mysql 5.5+ / Mariadb 5.5+ 3.Nginx(推荐) / A ...
- Apache Beam实战指南 | 手把手教你玩转大数据存储HdfsIO
https://mp.weixin.qq.com/s?__biz=MzU1NDA4NjU2MA==&mid=2247494843&idx=2&sn=0dd20caec76e25 ...
- 《Android编程权威指南》PhotoGallery应用梳理
PhotoGalley是<Android编程权威指南>书中另外一个重要的应用.
- SOS.dll (SOS Debugging Extension)
SOS.dll (SOS Debugging Extension) lays threads associated with a live thread. The -special option di ...
随机推荐
- 【.net 深呼吸】限制执行代码的权限
前面好几篇文章,老周都跟大伙伴们聊了跟应用程序域有关的话题,干脆咱们一聊到底吧,做学问就应该这样,有恒心. App Domain的创建新应用程序域的方法中,有一个特殊的重载: public stati ...
- FragmentTabHost的基本用法
开通博客以来已经约莫1个月了.几次想提笔写写东西,但总是由于各种各样的原因并没有开始.现在,年假刚结束,项目也还没有开始,但最终促使我写这篇博客的是,看了一篇博友写的新年计划,说是要在新的一年中写50 ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- ubuntu 下安装scrapy
1.把Scrapy签名的GPG密钥添加到APT的钥匙环中: sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 6272 ...
- CSS三个定位——常规、浮动、绝对定位
.dage { width: 868px; background: #5B8C75; border: 10px solid #A08C5A; margin-top: -125px; margin-le ...
- Android之文件数据存储
一.文件保存数据介绍 Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的.文件可用来存放大量数据,如文本.图 ...
- IOS之Objective-C学习 ARC下的单例模式
单例模式是我常用的一种设计模式,最常见的用途就是用来保存数据并且传递数据.这都归功于单例模式的特性,首先就让我为大家简单介绍一下单例模式的特性. 单例模式的三大特性: 1.某个类只能有一个实例: 2. ...
- mysql数据库主从同步
环境: Mater: CentOS7.1 5.5.52-MariaDB 192.168.108.133 Slave: CentOS7.1 5.5.52-MariaDB 192.168. ...
- 保护ASP.NET 应用免受 CSRF 攻击
CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/ ...
- HBase笔记:对HBase原理的简单理解
早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...