zoukankan      html  css  js  c++  java
  • windbg分析iis站点内存泄漏问题

    在一次上线过程中iis内存飙升,随后跟运维要到站点的dump文件,使用windbg分析了clr的内存分配,找到了问题的症结,先记录如下:

    使用windbg加载dump文件

    1.打开windbg,File->Open Crush Dump,打开dump文件;
    2.设置符号路径和站点发布文件路径
    .sympath C:MyCodesSymbols*SRV*C:MyLocalSymbols*http://msdl.microsoft.com/download/symbols:C:UsersAdministratorDesktopsymbol  
    其中,C:UsersAdministratorDesktopsymbol是pdb文件所在目录,C:MyCodesSymbols和C:MyLocalSymbols均为新建文件夹存放符号文件
    3.加载sos.dll和clr.dll
    .load sos.dll,clr.dll文件所在的目录(可以拷贝这两个dll放在pdb文件目录下)
    4.加载pdb文件 .symfix
    5.加载.reload
    6.输入命令.loadby sos clr
     
    使用windbg命令查看堆内存
    1.使用命令!dumpheap -stat 根据内存大小排序查看堆上的对象,查看占用内存比较高的对象和数组等,通过添加 -min 或者 -max 指定最小或者最大size的对象,首次执行这个命令不要添加 -min参数筛选,因为有可能就是一些小的对象比较多引起的内存问题。

    2.使用!dumpheap -mt命令查看mt(method table)中的对象地址,上图的第一列为mt,查看指定的MT并显示出Address

    !dumpheap -mt 000007fe9a25ebe8

    第一列为对象地址(address),可以看到mt的statistic

    3.进入这个地址查看具体的对象 !do 000000048a0eb1b0

     

    4.查看对象引用 !gcroot 000000048a0eb1b0

     

    5.根据上图中的线程线程信息定位线程ID,进入线程

    !threads命令查看工作的线程,71为线程ID

    6.进入71线程:~71s,下图所示已经进入71线程

    7.使用!clrstack 命令查看该线程的堆栈信息

    上图可以清晰的看到大的对象经过了哪些方法的调用,再结合代码,可以定位出问题。

    附录(windbg命令)

    内存状态:

    !EEHeap -GC 显示托管堆统计信息
    !EEHeap -loader 显示加载程序数据结构统计信息
    !DumpHeap -stat 显示垃托管堆各类型统计信息
    !DumpHeap -type Free -stat 显示所有碎片类型统计信息
    !DumpHeap -type System.String -min 150 -max 200 显示所有System.String类型 -min -max 字节统计信息
    !DumpHeap -min 85000 -stat 显示大对象统计信息
    !DumpHeap -mt 选项仅列出与指定的 MethodTable 结构对应的那些对象
    !DumpHeap -mt 00000000022245b0 -min 85000 查看MT 00000000022245b0中大对象
    !DumpHeap -stat 023e1000 033db630 按地址统计
    !DumpArray 显示数组对象
    !DumpObj (!do) 显示有关指定地址处的对象的信息
    !ObjSize 显示指定对象的大小
    !DumpStackObjects (!dso) 显示在当前线程内找到的所有托管对象
    !GCRoot 显示有关对指定地址处的对象的引用(或根)的信息。
    !CLRUsage 显示托管堆统计信息(GC堆大小,提交内存,虚拟内存),psscor4的扩展命令
    !DumpMT 显示有关指定地址处的方法表的信息。
    !DumpMT -MD 显示有关指定地址处的方法表所有方法的列表。
    !address -summary 显示最大可用区域
    !vmstat 最大可用区域是 MAXIMUM 列中的最大值

    线程调用:

    !ThreadPool 显示有关托管线程池的信息,包括队列中工作请求的数目、完成端口线程的数目和计时器的数目
    !Threads 显示进程中的所有托管线程
    !Threads -live 选项显示与活动线程关联的线程
    !Threads -pecial 选项显示由 CLR 创建的所有特殊线程
    !ThreadState 显示线程的状态。 value 参数为 Threads 报告输出中的 State 字段的值。
    ~54s 转到54线程
    !CLRStack 提供当前托管代码的堆栈跟踪。
    !CLRStack -p 选项显示托管函数的参数。
    !CLRStack -l 选项显示有关帧中的局部变量的信息。
    !DumpStack 显示堆栈跟踪 包括非托管。 
    !DumpStack -EE 命令仅显示托管函数。
    !EEStack 对一个进程中的所有线程运行 DumpStack 命令。
    k 显示当前线程的call stack
    kb 显示当前线程的call stack
    ~*kb 显示所有线程的call stack 可以 寻找线程中触发GC的函数(mscorwks!SVR::GCHeap::GarbageCollectGeneration)
    !ASPXPages 显示当前处理的HttpContext,psscor4的扩展命令
    !SyncBlk 显示同步块

    其它:
    !runaway 显示线程cpu时间
    vertarget 查看系统运行时间
    !PrintException (!pe) 显示在当前线程上引发的最后一个异常
    !address 命令显示某一地址上的页信息
    !SaveModule 将加载到内存中指定地址的图像写入指定文件,lm 列出的
    !SaveModule 081f0000 d:\commandobject.dll 
    !FinalizeQueue 显示所有已进行终结注册的对象。
    !GCHandles 显示有关进程中的垃圾回收器句柄的统计信息。

    S 可以搜索内存 在内存中搜索sina.com: s –u 0012ff40 L?8000000 “sina.com”
    r 显示寄存器的信息
    d 显示内存地址上的值 使用d命令显示esp寄存器指向的内存,默认为byte: d esp
    用dd命令直接指定054efc14地址,第二个d表示用DWORD格式: dd 054efc14

    域,程序集,类
    !DumpDomain 枚举在指定的 AppDomain 对象地址内加载的每个 Assembly 对象。若在调用 DumpDomain 命令时不提供任何参数,则将列出过程中的所有 AppDomain 对象
    !DumpAssembly 显示有关程序集的信息。DumpAssembly 命令将列出多个模块(如果存在)。
    !DumpModule  显示有关指定地址处的模块的信息。 可以使用 DumpDomain 或 DumpAssembly 命令检索模块的地址
    !DumpModule [-mt] 选项显示模块中定义的类型和模块所引用的类型
    !FindAppDomain 确定指定地址处的对象的应用程序域

    !IP2MD <Code address> 显示已 JIT 编译的代码中指定地址处的 MethodDesc 结构。
    !DumpMD <MethodDesc address>
    !U <MethodDesc address> | <Code address> 显示由方法的 MethodDesc 结构指针或方法体内的代码地址指定的托管方法的反汇编(带有批注)


     
     
  • 相关阅读:
    年轻人的第一个 Spring Boot 应用,太爽了!
    面试问我 Java 逃逸分析,瞬间被秒杀了。。
    Spring Boot 配置文件 bootstrap vs application 到底有什么区别?
    坑爹的 Java 可变参数,把我整得够惨。。
    6月来了,Java还是第一!
    Eclipse 最常用的 10 组快捷键,个个牛逼!
    Spring Cloud Eureka 自我保护机制实战分析
    今天是 Java 诞生日,Java 24 岁了!
    厉害了,Dubbo 正式毕业!
    Spring Boot 2.1.5 正式发布,1.5.x 即将结束使命!
  • 原文地址:https://www.cnblogs.com/linybo/p/13273300.html
Copyright © 2011-2022 走看看