dump文件解析之探索.Net的内存
前言:
对于需要长时间运行的.net程序,有时需要我们查看内存的使用有没有内存泄露问题。
我们可以从dump文件中找到答案。
Dump的看点
用dump文件来分析内存,到底我们需要关心哪些点呢?
- 内存的使用情况 HeapSize/object的数量 也就是托管堆使用大小以及托管堆内有多少数量的对象
1.1 查看有没有存在有占用大量内存的对象 <比如有某类下面的一个集合>
1.2 0 1 2各代的size<查看各代的内存是否有异常>
2.调查是否有内存泄露(重点)
2.1 查看object的根(Root) 看看GC回收不了的有哪些
2.2<我们知道一个对象Root下没有引用就会标为可Gc对象,如果一个对象你希望被gc回收但写代码不注意又在别的地方保存了引用就会出现内存泄露>
3. 终结器是否被阻塞时,当终结器线程被阻塞时,Finalize会等待累积(末尾有例子)
用什么工具
- Visual Studio
- DebugDiag
- WinDbg
- dotMemory(JetBrains旗下的 我还没研究过)
以上三款是微软给我们提供的工具,注意VS得要是Enterprise才可以哦。其他的两款都是免费的。
我们先写一个sample程序

然后运行


一.用Visual Studio
打开dump文件

点击按钮 【调试托管内存】

可以很清楚的看到有多少对象,每个对象共使用了多少内存
在这个一览下方有2个视图 分别是
1.根的路径

比如我们选择 ConsoleApp2.B 这个对象

从这个图可以看出来 B 这个对应 的 Paths To Root的追溯情况 (也就是构建最终要GC的Root)
Program._values(static变量) -> List<A> -> B
我们可以看到values就是B的Root 只要values不存在那B就会纳入gc的回收对象中
因为我们是在Hold住了这个程序的main方法所以在这个时候B 对象还不能被gc回收
2.引用的类型

如何我们选择List<ConsoleApp3.A>
那么就会展示List<ConsoleApp3.A>的引用关系如下图所示:

从这个图我们可以看出来 List<A> 持有 A[] ,A[]持有 A,A持有B
以上根据这2个视图我们可以利用Vs来看出:
咦?这个对象占用内存怎么这么大 有点可疑
这个对象不是应该被gc吗,怎么没有被gc呢?研究下他的gc root看看
二.DebugDiag
下载地址 https://www.microsoft.com/en-us/download/details.aspx?id=49924

点击 【Add Data Files】 添加Dump文件后 点击 【Start Analysis】 执行
执行成功后会自动用 IE 打开。

其实和 VS比起来差不多,直接生成一个报告也是比较方便的!
三.WinDbg
虽然使用上比较麻烦但是winDbg可以帮助我们分析的更加详细
可以从微软官方下载,为了方便百度云下载地址:
链接: https://pan.baidu.com/s/1eblPm4nuN0F-DkY_FzqUvA 提取码: zmtd
注意要设置下Symbol Path

重新设置符号文件路径如下;
SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols

意思是如果在本地找不到则从微软网站下载
Ok设置完成后用WinDbg载入dump文件

如下图所示:

打开成功后我们还不能开始分析必须
要先执行加载SOS和CLR(对于.Net Runtime 4.0)
【 !loadby sos clr】 命令
接下来我们用WinDbg来调查内存使用情况:
一般我们定位内存泄露问题,我总结的原则是要查到什么对象占用了大量内存,为什么它没有被GC。我们分以下几个步骤
1.统计内存中的对象&查找有异样的对象
使用命令 【!DumpHeap -stat】
可以把堆中的对象类型和size给打印出来

我们可以看出来 A 和 B 是可疑对象
2.根据类型查找存活对象一览
接下来我们根据查找出A的一览
使用命令【!DumpHeap -live -mt <MT addr>】

结果如下:

可以看出内存中A类型的对象有100000个
3.探索从某个对象找出GC ROOT一览
使用命令【!GCRoot 】


其实可以看出来和Visual Studio的【根的路径】要点差不多吧。
WinDbg的其他常用命令
1. !DumpHeap -stat 查找托管堆按类型分组统计个数以及占用的总内存大小

2.!HeapStat 查找当前堆中各代的内存使用量 以及剩余使用量

3.!DumpHeap -live -mt <MT addr> 从MethodTable中查找存活的对象一览

4.!DumpHeap -dead -mt <MT addr> 从MethodTable中查找要在下次FullGC要回收的一览

5.!DumpMT -md <MT addr> 查看类型信息 (加了-md参数会把这个类型下的方法(MethodDescriptor)都打印出来)

6.!DumpClass <EEClass addr> 指定EEClass的地址

7.!Threads 查看Finalizer有没有导致死锁的例子

如上图所示, 用!Threads可以找出 Finalizer的线程为13.。接下来用命令 ~13k 查看线程执行栈,

上图是正常的情况没有问题。执行WaitForFinalizerEvent等下一次执行信号
下图是死锁情况

可以看到有 CallFinalizer 和 FinalizeAllObjects 表示正在处理什么东西
在用命令【~[ID]e!clrstack】查看CLR的执行栈情况

可以看出是在Finalize里面用了 Thread.Sleep导致的
使用SOSEX更方便的使用WinDbg
sosez是sos的扩展工具集(就是一个dll文件),下载官网地址:http://www.stevestechspot.com/
下载完后要加载到 WinDbg里面去 使用命令 .load 进行加载

它集成了很多简单使用的指令
例如: !mdt 可以根据 类型 进行筛选

蓝色处可以直接点击查看,功能很强大

总结
.Net程序运行期间会遇到很多奇怪的问题,通过分许Dump文件分析内存情况是一个很好的切入口。
不管用什么工具,按照以下几个步骤:
- 统计内存中的对象
- 查找有异样的对象 比如这个对象数量多的有点反常,本来期待会被GC回收但是却没有
- 根据类型查找存活对象一览
- 探索从某个对象找出GC ROOT一览
一定会让你有所发现。
dump文件解析之探索.Net的内存的更多相关文章
- Dump文件的生成和使用
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/lk142500/article/detai ...
- 如何使用dump文件进行调试
转载[文尾出处链接] 1 简介第一次遇到程序崩溃的问题,之前为单位开发了一个插件程序,在本机运行没有出现问题,但把生成的可执行文件拷贝到服务器上一运行程序,刚进入插件代码,插件服务就崩溃了,当时被这个 ...
- 记一次dump文件分析历程
一.背景 今天下午,正酣畅淋漓的搬砖,突然运维同事在群里通知,核心服务某个节点内存异常,服务假死.神经一下子紧张起来,赶紧跑到运维那边观察现象. 观察的结果是服务内存溢出,该服务是核心服务,分配了5G ...
- dump解析入门-用VS解析dump文件进行排障
突然有一天部署在服务器的一个应用挂掉了,没办法只能进入服务器打开 [事件查看器]查看下,好不容易找到了打开后一脸懵逼 事件查看器查到的内容根本对我们排障没有任何作用. 在这个时候如果有对应的dump文 ...
- 使用Windbg解析dump文件
WinDbg OllyDbg SoftICE (已经停止更新) 虽说WinDbg在无源码调试方面确实比较困难,但在调试内核方面却真的有独到之处. https://www.pediy.com/kssd/ ...
- jvm内存快照dump文件太大,怎么分析
1.场景 通常,使用eclipse的mat图形化工具打开dump的时候都会内存溢出. 对于比较小的dump,eclipse可以打开,但一旦dump文件太大,eclipse就有点束手无策. 这时候怎么办 ...
- 【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
1.首先,java程序启动在linux,怎么生成dump文件? 1>第一步,首先你需要得到java程序的PID,最简单的方法使用如下命令 ps -ef|grep java 或者如果是docker ...
- centos7 lldb 调试netcore应用的内存泄漏和死循环示例(dump文件调试)
写个demo来玩一玩linux平台下使用lldb加载sos来调试netcore应用. 当然,在真实的产线环境中需要分析的数据和难度远远高于demo所示,所以demo的作用也仅仅只能起到介绍工具的作用. ...
- C# 异常内存信息导出Dump文件
背景:很多情况下程序崩溃我们只能看到程序抛出来的异常信息,但是有时候异常信息不清不楚我们处理异常还是一头雾水,这种情况下我们就很希望能有种办法获取程序运行时的内存进行调试,查看其中的变量.参数.方法执 ...
随机推荐
- Appium在Android7.0及以上系统运行时报错的解决方案
背景:在使用Samsung S系列手机进行自动化测试时,发现同样脚本的情况下华为荣耀系列可以正常运行,最终发现差异在于Android7.0及以上系统和appium版本不匹配,需要升级appium.但需 ...
- wiringPi库的pwm配置及使用说明
本文介绍树莓派(raspberry pi)在linux c 环境下的硬件pwm配置及使用方法. 1. 下载安装wiringPi 此步骤建议参考官网指南,wiringPi提供了对树莓派的硬件IO访问,包 ...
- IDLE打开Python报错 api-ms-win-crt-runtimel1-1-0.dll缺失的解决方案
1.此方法转载至 http://blog.csdn.net/lt_java13/article/details/78814676 2.把C:\Windows\SysWOW64的api-ms-win-c ...
- docker初体验,搭建自用的gitlab服务
一.前言 git在如日中天的版本管理系统,现在如果不是工作在git版本管理系统下,几乎都不好意思给人打招呼.现在就有现成的互联网的git服务器提供给大家使用,例如号称程序的社交网络github. 正好 ...
- 从零开始学习PYTHON3讲义(十一)计算器升级啦
(内容需要,本讲中再次使用了大量在线公式,如果因为转帖网站不支持公式无法显示的情况,欢迎访问原始博客.) <从零开始PYTHON3>第十一讲 第二讲的时候,我们通过Python的交互模式来 ...
- 【Android Studio安装部署系列】六、在模拟器上运行项目
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 在模拟器上运行项目的步骤.不过在实际开发中,一般不采用这种方式,因为影响电脑的运行,所以一般使用真机运行项目. 运行项目 创建模拟器 ...
- Asp.Net Core 轻松学-一行代码搞定文件上传
前言 在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建自定义绑定模型来实现文件上传. 1. 实现自定义绑定模型 1 ...
- Windows Server 2019 容器化探索-Docker安装
Docker on Windows Server 2019 微软自Windows Server 2016开始支持Docker,今天我们将介绍在Windows Server 2019上安装并使用Dock ...
- 关于CSS引入方式的详细见解
关于CSS的发展史这里不做介绍.写博客的原因之一是想帮助那些与我一样喜欢纠结的初入前端的伙伴,希望自己写的帖子能对伙伴有些许帮助:原因之二这些帖子也算自己的一个知识的整理.现在还没有一定的顺序可循,但 ...
- SpringCloud-sleuth-zipkin链路追踪
什么是Zipkin? 它是一个分布式链路跟踪系统它可以帮助收集时间数据,每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序:如果想解决延迟 ...