dump文件解析之探索.Net的内存

前言:

对于需要长时间运行的.net程序,有时需要我们查看内存的使用有没有内存泄露问题。

我们可以从dump文件中找到答案。

Dump的看点

用dump文件来分析内存,到底我们需要关心哪些点呢?

  1. 内存的使用情况 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等下一次执行信号

参考 https://github.com/dotnet/coreclr/blob/ca013149100a9ccc69a5df5b80f29fed2b1b0ce8/src/vm/finalizerthread.cpp#L571

下图是死锁情况

可以看到有 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一览

一定会让你有所发现。

原文地址:https://www.cnblogs.com/yudongdong/p/9701727.html

时间: 2024-10-07 22:09:55

dump文件解析之探索.Net的内存的相关文章

Dump文件的生成和使用

1 简介 第一次遇到程序崩溃的问题,之前为单位开发了一个插件程序,在本机运行没有出现问题,但把生成的可执行文件拷贝到服务器上一运行程序,刚进入插件代码,插件服务就崩溃了,当时被这个问题整的很惨,在同事的帮助下了解到,对于程序崩溃,最快的解决方式是生成dump文件,通过生成dump文件使用调试工具进行调试,还原程序崩溃时的状态,能够起到快速定位排查问题的作用.Dump文件是进程的内存镜像.可以把程序的执行状态通过调试器保存到dump文件中.Dump文件是用来给驱动程序编写人员调试驱动程序用的,这种

redis快照文件dump.rdb解析工具--redis-rdb-tools

解析Redis dump.rdb文件,分析内存并将数据导出到JSON Rdbtools是Redis的dump.rdb文件的解析器.解析器生成类似于xml sax解析器的事件,并且非常有效的内存明智. 此外,rdbtools还提供实用程序: 在所有数据库和密钥中生成数据的内存报告 将转储文件转换为JSON 使用标准差异工具比较两个转储文件 Rdbtools是用Python编写的,虽然有其他语言的类似项目.请参见常见问题以获取更多信息. 安装rdbtools 前提条件: redis-py是可选的,只

收集JVM内存dump文件

Java服务出现假死的现象(如网页打不开.打开空白页面.访问速度极剧下降),则需要工程师在第一时间dump JVM 内存数据,用以分析原因.那么怎样获取JVM内存dump文件呢? 在Windows的CMD控制台或者Linux终端下执行: jmap-dump:format=b,file=YYMMddhhmm.dump pid (其中YYMMddhhmm自定义的文件名:pid可以使用Jconsole进入Java监视和管理控制台上查找). 注意:使用 jmap 命令可能会导致网站对外服务暂停,请尽减少

eclipse memory analyzer对系统内存溢出堆文件解析(转)

本文转之:https://blog.csdn.net/rachel_luo/article/details/8992461 前言 性能分析工具之-- Eclipse Memory Analyzer tool(MAT)(一)中介绍了内存泄漏的前因后果.在本文中,将介绍MAT如何根据heapdump分析泄漏根源.由于测试范例可能过于简单,很容易找出问题,但我期待借此举一反三. 一开始不得不说说ClassLoader,本质上,它的工作就是把磁盘上的类文件读入内存,然后调用java.lang.Class

jvm内存快照dump文件太大,怎么分析

来自凌幽草 1.场景 通常,使用eclipse的mat图形化工具打开dump的时候都会内存溢出. 对于比较小的dump,eclipse可以打开,但一旦dump文件太大,eclipse就有点束手无策. 这时候怎么办呢?可以使用linux下的mat,既Memory Analyzer Tools 2.dump生成 dump可以是内存溢出时让其自动生成,或者手工直接导.配置jvm参数-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/biapp/

使用jdk自带工具jvisualvm 分析内存dump文件

1.获取dump文件 使用 以下命令 创建 进程PID = 16231的 dump文件,命名为 order.hprof jmap -dump:format=b,file=order.hprof 16231 将文件下载到本地. 2.使用jdk bin目录下的jvisualvm.exe 装入 order.hprof 分析对应对象的占用内存 原文地址:https://www.cnblogs.com/wangzun/p/11613051.html

tomcat内存泄漏存入dump文件

很多tomcat进程退出(或者进程假死),都是由于频繁的抛出OutOfMemeoryError导致的. 为了让tomcat退出前或者发生OutOfMemeoryError时自动dump堆栈信息,方便事后排查问题,我们可以做如下操作: 1. 在tomcat启动参数中加入两个参数 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/home/tomcat/domains/server2/oom.hprof 2. 重启tomcat 参数说明

C++PE文件格式解析类(轻松制作自己的PE文件解析器)

PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣的能够參看之后列出的參考资料及其它相关内容. 近期我也在学习PE文件格式,參考了很多资料.用C++封装了一个高效方便的PE文件格式解析的类. 该类对想学PE文件结构的朋友可算一份可贵的资料.代码均非常易懂,考虑较全面,具有一定的通用性. 同一时候该类也能够让想创建自己的PE文件解析软件的朋能够轻松在

Java Heap dump文件分析工具jhat简介

jhat 是Java堆分析工具(Java heap Analyzes Tool). 在JDK6u7之后成为标配. 使用该命令需要有一定的Java开发经验,官方不对此工具提供技术支持和客户服务. 用法: jhat [ options ] heap-dump-file 参数: options 可选命令行参数,请参考下面的 Options heap-dump-file 要查看的二进制Java堆转储文件(Java binary heap dump file). 如果某个转储文件中包含了多份 heap d