利用SOS分析调试托管代码--(2)
- 查看线程和同步块
- 查看GC
- 其他诊断工具
1.查看托管线程
Threads命令显示进程中的所有托管线程及统计信息。-special选项显示由 CLR 创建的所有特殊线程,包括GC线程、调试器帮助程序线程、终结器线程、 AppDomain卸载线程和线程池计时器线程。
Threads
!Threads -special
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
11820 1 2e2c 003e7ee8 8a028 Enabled 01b0ba14:01b0c004 003e16b0 1 MTA
10364 2 287c 003e99a0 b228 Enabled 00000000:00000000 003e16b0 0 MTA (Finalizer)
OSID Special thread type
10364 287c Finalizer
可以看到当前有2个线程,1个属于后台线程。线程2是终结器线程。我们还可以看到线程1存在一个锁。
2.查看线程状态
线程State只是一个值,我们需要得到具体的描述,可以利用ThreadState命令显示线程的状态。value参数为Threads输出中的State字段的值。
我们查看线程1的状态。
ThreadState
!ThreadState 8a028
Debug Suspend Pending
Legal to Join
CoInitialized
In Multi Threaded Apartment
Sync Suspended
3.查询线程同步块
线程同步块结构是一个容器,用于存放无需为每个对象创建的额外信息。比如COM互操作数据、哈希代码和用于线程安全操作的锁定信息。
我们可以用syncblk命令查询所有的线程同步块。
SyncBlk
!SyncBlk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
1 0043f9ac 1 1 003e7ee8 2e2c11820 01b0b22c Wuhong.SOSTest.Complex
-----------------------------
Total 1
CCW 0
RCW 0
ComClassFactory 0
Free 0
可以看到有线程1的类型为Wuhong.SOSTest.Complex的对象上拥有1个同步块。
1.查看托管堆统计
HeapStat命令显示每个堆的生成大小及每个堆上各生成的可用空间总量。-inclUnrooted选项包括有关不再为根的垃圾回收集合堆中的托管对象的信息。
HeapStat
!HeapStat -inclUnrooted
Heap Gen0 Gen1 Gen2 LOH
Heap0 45048 12 12 8784
Free space: Percentage
Heap0 12 0 0 64SOH: 0% LOH: 0%
Unrooted objects: Percentage
Heap0 11328 0 0 0SOH: 25% LOH: 0%
2.查看GC句柄
利用GCHandles命令可以显示进程中的垃圾回收器句柄的统计信息。
GCHandles
!GCHandles
GC Handle Statistics:
Strong Handles: 10
Pinned Handles: 4
Async Pinned Handles: 0
Ref Count Handles: 0
Weak Long Handles: 0
Weak Short Handles: 0
Other Handles: 0
Statistics:
MT Count TotalSize Class Name
605ff5e8 1 12 System.Object
60601b18 1 28 System.SharedStatics
60603670 1 36 System.Security.PermissionSet
605fffcc 1 48 System.Threading.Thread
605ffde8 1 84 System.ExecutionEngineException
605ffd9c 1 84 System.StackOverflowException
605ffd50 1 84 System.OutOfMemoryException
605ffc0c 1 84 System.Exception
60600ec8 1 112 System.AppDomain
605ffe34 2 168 System.Threading.ThreadAbortException
605b6c28 3 8720 System.Object[]
Total 14 objects
可以看到进程中一共有4个固定句柄和10个强类型句柄。
3.查看终结器队列
利用FinalizeQueue命令,可以显示所有已进行终结注册的对象。-allReady 选项显示所有准备终止的对象,无论它们已被垃圾回收标记成这样,还是将被下一个垃圾回收标记。
FinalizeQueue
!FinalizeQueue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 3 finalizable objects (00428bb0->00428bbc)
generation 1 has 0 finalizable objects (00428bb0->00428bb0)
generation 2 has 0 finalizable objects (00428bb0->00428bb0)
Ready for finalization 0 objects (00428bbc->00428bbc)
Statistics for all finalizable objects (including all objects ready for finalization):
MT Count TotalSize Class Name
605ff4d0 1 20 Microsoft.Win32.SafeHandles.SafePEFileHandle
60605efc 1 44 System.Threading.ReaderWriterLock
605fffcc 1 48 System.Threading.Thread
Total 3 objects
4.查询对象的根
利用GCRoot可以显示有关对指定地址处的对象的引用(或根)的信息。搜寻范围是整个托管堆和句柄表,同时还搜索终结器队列。这个命令可以用来确认对象为什么没有被垃圾收集。
比如我们想查看DumpObj小节中类型为Wuhong.SOSTest.Complex的对象的根。
GCRoot
!GCRoot 0x01b0b22c
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 11820 OSTHread 2e2c
ESP:28ecbc:Root: 01b0b22c(Wuhong.SOSTest.Complex)
ESP:28edfc:Root: 01b0b22c(Wuhong.SOSTest.Complex)
ESP:28f08c:Root: 01b0b22c(Wuhong.SOSTest.Complex)
ESP:28f09c:Root: 01b0b22c(Wuhong.SOSTest.Complex)
ESP:28f0e0:Root: 01b0b22c(Wuhong.SOSTest.Complex)
ESP:28f0e4:Root: 01b0b22c(Wuhong.SOSTest.Complex)
Scan Thread 10364 OSTHread 287c
可以看到这个对象在线程1中有6个引用。
5.查询对象在GC堆中的位置
GCWhere命令显示垃圾回收堆中参数传入的位置和大小。
GCWhere
!GCWhere 0x01b0b22c
Address Gen Heap segment begin allocated size
01b0b22c 0 0 01b00000 01b01000 01b0c010 0x18(24)
6.查询GC堆
只要得到对象在堆中的地址,就可以用DumpHeap显示有关GC堆的信息和和相关收统计信息。
DumpHeap
!DumpHeap 01b0b22c
Address MT Size
01b0b22c 00133918 24
01b0b244 605ff9ac 64
object 01b0b284: does not have valid MT
curr_object: 01b0b284
Last good object: 01b0b244
----------------
02b01000 003e91d8 16 Free
02b01010 605b6c28 4096
02b02010 003e91d8 16 Free
02b02020 605b6c28 528
02b02230 003e91d8 16 Free
02b02240 605b6c28 4096
02b03240 003e91d8 16 Free
total 0 objects
Statistics:
MT Count TotalSize Class Name
00133918 1 24 Wuhong.SOSTest.Complex
605ff9ac 1 64 System.String
003e91d8 4 64 Free
605b6c28 3 8720 System.Object[]
Total 9 objects
我们可以看到堆中从命令输入地址开始的对象的排列,另外我们还注意到有个对象的方法表无效了。
1.查看进程信息
利用ProcInfo命令可以详细显示进程的环境变量、内核CPU时间和内存使用统计信息。这些信息在性能调试中非常有用。
ProcInfo
!ProcInfo
---------------------------------------
Environment
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\Administrator\AppData\Roaming
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=WUHONG
ComSpec=C:\Windows\system32\cmd.exe
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Users\Administrator
lib=C:\Program Files\SQLXML 4.0\bin\
……
……
……
---------------------------------------
Process Times
Process Started at: 2011 Apr 27 15:35:42.44
Kernel CPU time : 0 days 00:00:31.93
User CPU time : 0 days 00:04:15.56
Total CPU time : 0 days 00:04:47.49
---------------------------------------
Process Memory
WorkingSetSize: 487144 KB PeakWorkingSetSize: 497100 KB
VirtualSize: 906484 KB PeakVirtualSize: 913984 KB
PagefileUsage: 235248 KB PeakPagefileUsage: 243036 KB
---------------------------------------
67 percent of memory is in use.
Memory Availability (Numbers in MB)
Total Avail
Physical Memory 3583 1153
Page File 4095 3056
Virtual Memory 2047 1162
2.查询曾经出现的OOM状况
利用AnalyzeOOM命令可以显示对GC堆进行分配请求时发生的最后 OOM 的信息。
AnalyzeOOM
!AnalyzeOOM
There was no managed OOM due to allocations on the GC heap
3.查询对象所在的AppDomain
利用FindAppDomain命令可以确定指定地址处的对象的AppDomain。
比如我们要确定DumpObj小节中类型为Wuhong.SOSTest.Complex的对象所在的AppDomain。
FindAppDomain
!FindAppDomain 0x01b0b22c
AppDomain: 003e16b0
Name: Wuhong.SOSTest.exe
ID: 1
4.验证GC堆或对象的有效性
在DumpHeap小节我们注意到了在GC堆上有1个对象的方法表无效了。可以用VerifyHeap命令验证整个堆是否有损坏,也可以用VerifyObj命令验证具体的对象。
对象损坏可能有多种原因,比如内存越界修改等。具体原因需要详细分析损坏的对象。
VerifyHeap
!VerifyHeap
-verify will only produce output if there are errors in the heap
object 01b0b284: does not have valid MT
curr_object: 01b0b284
Last good object: 01b0b244
----------------