1. 背景

在开发过程中,我们可能遇到应用程序线程占用过大的问题,可以通过windbg命令去定位哪些类型,哪些内存一直占用堆资源,从而查出问题,解决问题。

2. 准备工作

工具:

  • 抓取DUMP文件的工具,任务管理器(最简单),DebugDiag,ProcessExplorer等(网上很多)
  • 分析工具windbg

PS:使用任务管理器的时候需要强调一下如何抓包:根据你的进程是多少位的,然后使用对应位数的任务管理器去抓,

不然抓到的DUMP文件是无效的。

如果在下面分析过程中出现“SOS does not support the current target architecture”这样的错误,就是使用了64位的

任务管理器导出了32位进程的dump文件,下面是两个解决方法:
(1)使用32位任务管理器,运行:C:\Windows\SysWOW64\taskmgr.exe。
(2)使用其它转储工具,比如:ProcessExplorer。

3. 分析

抓取DUMP文件后,使用windbg工具打开,首先加载SOS.dll,CLR.dll文件。

备注:SOS是啥东西?SOS可以调试扩展,让你可以查看在CLR里面运行的代码的有关信息。

例如,你可以使用SOS调试扩展显示托管堆的有关信息,查找堆的错误,显示运行时使用的内部数据类型,

以及查看在运行时里面运行的所有托管代码的有关信息。

相关参考:https://www.cnblogs.com/ceachy/p/WinDBG_SOS.html

备注:以上加载sos.dll与clr.dll的时候可能报错,上面截图的错误是说你使用的dll版本与当前的windbg分析的DUMP文件位数不一致

(1) 加载SOS&CLR

在加载sos.dll与clr.dll的时候,首先你要确定你的DUMP文件的位数,如果是32位则可以使用如下方式加载:

.load C:/Windows/Microsoft.NET/Framework/v4.0.30319/sos.dll
.load C:/Windows/Microsoft.NET/Framework/v4.0.30319/clr.dll

如果是64位,则使用另外的加载方式:

.load C:/Windows/Microsoft.NET/Framework64/v2.0.50727/sos.dll
.load C:/Windows/Microsoft.NET/Framework64/v4.0.30319/sos.dll

  

其中,SOS 的命令格式 :![command] [options]

具体参考:https://www.cnblogs.com/kissdodog/p/3731743.html

(2)使用命令!dumpheap -stat 显示关于垃圾收集堆的信息和有关对象的收集统计:

图3-1

图3-2

以上命令执行后,输出结果的第一列是mt(method table)信息,表示类型对象的地址,我们可以使用此信息来明确指定我们感兴趣的对象在堆中的信息。

看到上面的数据,我们这些占用内存比较大的对象,此时有没有被引用?上面显示的是所有堆的整体占用信息,其实我们比较关心的还是被引用的对象的信息。

使用命令:!dumpheap -dead -min 85000  参数 -dead:表示仅输出没有没有被引用的对象 (这些对象将在下一个 Full GC 中被回收);

-min 85000 :表示查看大于85000bytes字节的对象

命令执行后发现:00000004b06ad190(占用48M)与00000004802fef20(占用49M)这两个对象都没有被引用了(挑了两个占用大的),那么 这些对象将在下一个Full GC中被回收。

相反,使用命令:!dumpheap -live -min 85000 查看的是还被引用的对象:

根据分析结果可以看出,占用比较大的是0000000484884750(占用24M),我们使用命令:!do 0000000484884750 

查看一下这个对象到底是何方妖孽:

上图的结果显示:其中占24M的数据对象,发现竟然是log的存储,天了噜!

这样不行,从图3-1中,再挑选一个业务性比较强的类型看看。

场景1:

选择查看StaffDto数据,首先还是执行命令:!DumpHeap -mt 000007fe9ba5eba0 查看显示有关垃圾收集堆和收集站的信息

以上命令输出第一列是Address,表示具体数据的地址,从上面可以看到这个StaffDto对象共有58515个,然后占堆内存30M,拿其中某一个看看

!dumpobj 000000038a71b7f0

打印EEClass结构,其中可以看到类型静态变量信息,可以根据MT信息查询其中的字段信息

看看里面的字段吧,!do 000000038a71ba60 (Email)

然后输入命令:!gcroot 000000038a71ba60(!gcroot 命令是用来查看其中某一个对象的引用根信息),看看其引用根:

我晕,竟然没有引用根。

备注:!gcroot是一个非常有用的命令,它能够帮助我们发现某对象上目前还存在的有效引用,这也是为什么GC还不回收这个对象的原因。

这个信息可以很好的帮助我们分析那些本应该没有引用,但却一直还存在有效引用的对象,

由此发现我们代码中潜在的内存泄漏,同时我们也可以观察到哪些对象是目前没有引用了。

场景2:

我们选择图3-2中最后那个string类型的对象数据:

!dumpheap -mt 000007fef828da88

结果分析发现:string类型的数据个数180W,占用222M内存,这也不用大惊小怪,代码程序中使用频繁的对象应该就是string了,接着往下看。

!dumpheap -mt 000007fef828da88 -min 85000 // 查看85K以上的string类型数据

命令执行结果显示:大于85K的string对象有8个,占98M,其中两个分别是42M与48M

那就重点观察这两个string类型的对象,使用命令

!dumpobj 00000004b06ad190 (等价于!do)

然后紧接着去分析这个对象的引用根信息,输入命令:!groot 00000004b06ad190 

这个对象竟然也没有有效引用根???

看看这个对象内容吧,使用命令:dc 00000004b06ad190 L1000(命令dc是查看对象内容,参数L代表显示多少行)

以上结果显示,这个48M的string内容是存的staffDto信息。

以上就是我根据网上的教程,然后拿着自己在服务器dump下来的文件进行的内存分析,windbg这个工具真的很锻炼人,慢慢从头学起吧!与君共勉~

转载于:https://www.cnblogs.com/walt/p/11391664.html

使用windbg定位内存问题【入门级】相关推荐

  1. 使用Windbg定位内存泄露

    在网上看了两篇文章,整理一下,大致内容如下: 场景一:运行Debug版本程序,用Windbg attach 上去,等程序退出时,基于内存泄露报告,定位内存泄露的位置. 首先使用windbg工具gfla ...

  2. umdh windbg分析内存泄露

    A.利用工具umdh(user-mode dump heap)分析 1设置gflags.exe标志 r Gflags标志设置好后,开启cmd 键入要定位内存泄露的程序gflags.exe /i mem ...

  3. 如何使用Eclipse内存分析工具定位内存泄露

    本文以我司生产环境Java应用内存泄露为案例进行分析,讲解如何使用Eclipse的MAT分析定位问题 一. 背景 11月10号晚上8点收到报警邮件,一看是OOM 打开公司监控系统查看应用各项指标发现J ...

  4. 一种定位内存泄露的方法(Linux)

    2019独角兽企业重金招聘Python工程师标准>>> 目的: 本文是<一种定位内存泄露的方法(Solaris)>对应的Linux版本,调试器使用gdb.主要介绍实例部分 ...

  5. 汇编程序-更灵活的定位内存地址方法

    汇编程序-更灵活的定位内存地址方法 如何灵活运用定位内存的方法呢?在之后,我们将列出几个实际例子.通过例子,展示定位内存的一些方法,熟悉和提升我们对汇编程序的理解. 大小写转化(1) 通过上面的汇编程 ...

  6. github snap android,GitHub - albuer/heapsnap: HeapSnap 是一个定位内存泄露的工具,适用于Android平台。...

    HeapSnap 1.HeapSnap 是什么 HeapSnap 是一个定位内存泄露的工具,适用于Android平台. 主要特性如下: 对系统负载低 不需要修改目标进程的源代码 支持Andoroid上 ...

  7. 【Android 逆向】Android 逆向基本概念 ( 定位内存中的修改点 | 基址寻址法 | 搜索定位法 )

    文章目录 一.定位内存中的修改点 1.基址寻址法 2.搜索定位法 一.定位内存中的修改点 使用 " 基址寻址法 " 或 " 搜索定位法 " 搜索 指定文件中的代 ...

  8. 汇编: 更灵活的定位内存地址的方法

    bx是偏移地址寄存器.同样的, si,di也是偏移地址寄存器. 这样使用了si,di可以更灵活的定位内存地址. assume cs:codecode segmentstart: mov bx,0mov ...

  9. 更灵活的定位内存地址的方法---汇编学习笔记

    更灵活的定位内存地址的方法 前面,我们用[0].[bx]的方法,在访问内存的指令中,定位内存单元的地址.本章将用更灵活的方式来定位内存地址. 7.1 and和or指令 (1)and指令:逻辑与指令,按 ...

最新文章

  1. 面试官:说说Kafka处理请求的全流程
  2. 每日一皮:程序员最讨厌的四件事!
  3. “挤掉”优衣库的Ubras、蕉内、内外等新内衣品牌们,到底牛在哪?
  4. linux qt libs,linux下qt使用第三方库的那些事
  5. 如何查看Linux版本号(内核版本号和发行版本号)
  6. 【LeetCode笔记】25. K个一组翻转链表(Java、链表、递归)
  7. 第四节 字符串属于值类型
  8. post的4个参数和ajaxReturn方法
  9. python md5加密字符串_python md5加密字符串的例子
  10. 什么情况下document.write会覆盖页面及覆盖原理解释
  11. 思科命令大全_【汇总】思科网络设备产品型号大全!超全解释~
  12. FydeOS | ChromeOS配置Flutter开发环境
  13. Python分析与处理---利用Python进行学生成绩分析
  14. 海定计算机计算标准差,方差 标准差
  15. java达内小发猫课程,详细说明
  16. 2019迅雷校园招聘后端工程师面试总结
  17. tail命令,实时查看日志文件
  18. iOS ZBarSDK 用ZBarReaderView自定义二维码扫描界面
  19. Git之cherry-pick
  20. 每日思考第 63 期:物理空间限制精神世界的发展

热门文章

  1. 在ubuntu 16.04下安装gitlab(摘抄中文官方网站)
  2. 1 Strut2 Mapping to MVC
  3. getOutputStream() 的问题
  4. 从Asp.net转到Php之调试
  5. R语言 赋值符号 的区别
  6. mysql查询后10条数据类型_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...
  7. hive导数据到mysql 自增主键出错_老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”...
  8. html手机怎么样删除掉,怎么样才能删除这个叫做(手机模拟器大师)的软件?...
  9. java对象转json字符串日期格式_fastJSON字符串类型数据中的日期转换为Java bean的日期对象...
  10. python函数注释 参数 省略号_python – make函数在help()函数中有参数的省略号