.Net 內存對象分析

在生產環境中,經過運行日誌咱們會發現一些異常問題,此時,咱們不能直接拿VS遠程到服務器上調試,同時日誌輸出的信息沒法百分百反映內存中對象的狀態,好比說咱們想查看進程中全部的Socket鏈接狀態、服務路由信息等等。windows

即:如何分析.Net 運行時內存對象?緩存

因此,今天咱們推薦.Net進階必備神器:Windbg,基於Windbg分析內存中對象的狀態。服務器

仍是以實際場景爲例吧,這樣能夠更加貼合實際應用,同時更有借鑑意義。網絡

業務場景:分佈式環境下,各個服務容器進程中緩存了各個服務的Socket鏈接信息,方便運行時服務間相互訪問。可是網絡是偶爾要抖動的,在抖動的一瞬間,不少Socket鏈接便中斷了,服務調用方收到的異常信息即是:鏈接已中斷等。編輯器

如何快速定位到哪些Socket鏈接是中斷的?這些中斷的Socket鏈接是鏈接的哪些服務器、端口?這些信息能夠幫助咱們分析具體的網絡問題,同時作一些程序上的補償:鏈接重建。一個目標,保持程序的高可用性!分佈式

那麼,請出咱們今天的主角:Windbg,微軟的官方介紹:工具

http://windbg.org/spa

進一步說,咱們須要抓取指定進程某一瞬間的內存鏡像,而後使用Windbg分析內存中各類對象、線程、線程池、析構隊列、堆、CPU內核時間片等的狀態。操作系統

所以,第一步,咱們須要對要進行內存分析的進程,抓取一個Full Dump文件:內存鏡像文件。線程

任務管理器->選擇進程->建立轉儲文件

系統會將Dump文件存儲在指定的目錄,這個目錄須要拷貝一下,以備用。

第二步,從下面路徑下載並安裝Windbg

https://developer.microsoft.com/en-us/windows/hardware/download-windbg

請根據操做系統的位數,選擇X86或者X64。這裏咱們用的64位操做系統,選擇的Windbg(X64)

第三步:Ctrl+D,打開剛纔抓取的Dump文件

第四步:加載調試用的SOS.dll: .loadby sos clr

.loadby sos clr

第五步:查看內存中指定類型的對象 

!dumpheap -Type Socket

這裏的Socket是具體的類型,咱們要查看Socket鏈接狀態,因此類型是Socket

這裏的Header中MT=Method Table

咱們須要用的MT:00007ffafe50d700

第六步,查看內存全部全部的Socket對象的地址:

!dumpheap -mt 00007ffafe50d700

 

輸出結果中,第一列是某一個Socket對象的內存地址

此時,咱們可使用下面的命令,隨機查看一個Socket對象的信息:

!do 000001b2d188ae00

!do 的意思:!dumpObj 

 那麼問題來了,幾百個Socket對象,若是一個一個!do查看,這工做量太大了! 固然不能這麼幹,Windbg有.foreach命令

 搜索Debugging help.chm文檔,.foreach給了個樣例:

.foreach /f ( place "g:\myfile.txt") { dds place } 

即,循環遍歷一個文本文件,對每一行數據,執行一個命令操做。

好,咱們回到咱們上一步的輸出中:每一個Socket對象的地址列表,咱們拷貝出來,用文本編輯工具只取出第一列(Socket地址列),保存成1.txt

第七步:循環遍歷查看每一個內存對象

.foreach /f (adr "C:\1.txt") {!do adr}

輸出:

將全部的輸出,拷貝到文本編輯器中,搜索查詢指定的屬性,例如m_IsConnected=0, 便可找出鏈接斷開的Socket對象,而後進一步用!gcroot 查看這個對象的引用關係,再一步一步看各個引用對象的信息就能夠大體分析了。

 

以上就是.Net 內存對象分析的整個過程,分享給你們。

 

周國慶

2017/10/06

相關文章
相關標籤/搜索