1、利用任務管理器或者 jps
命令找到我的程序的進程ID
在cmd控制台下輸入jps
命令,即可列出當前電腦運行的java程序的所有進程,我的程序的進程ID為26028
2、利用 jstack 命令列出進程的所有信息
使用命令jstack 26028 > 26028.txt
列出進程ID為26028的進程信息,並輸出到26028.txt文本文件中。
之后打開這個文件可以看到當前進程的所有線程信息,包括線程的狀態、線程的ID號以及堆棧信息等。
在文件的最后,我們會看到幾個負責GC的線程,nid就是線程的ID:
3、使用 pslist 工具查看進程的所有線程的詳細信息
在cmd控制台輸入pslist,如果命令不被識別,則表示當前電腦上沒有安裝pslist這個工具,可以到windows官方網站:
https://technet.microsoft.com/en-us/sysinternals/bb896682.aspx下載,下載完成后將其解壓到C:\Windows\System32
路徑下即可使用,或者將其配置到環境變量中亦可。
安裝完成后,使用pslist -dmx 26028 > 26028_pslist.txt
命令,可以列出進程ID為26028的進程下的所有線程的詳細信息(線程ID、上下文切換,狀態等)。
打開輸出的文件,可以看到:
從這個文件所列的信息中,我們可以找到最耗資源的線程。然后將其Tid(線程ID)轉換成十六進制(直接利用windows下的計算器即可),到使用jstack
命令產生的文件中查找,可以查到具體哪一個線程在干什么,為什么這么耗資源?
最后,我發現我的程序最耗資源的線程是所有GC線程,而程序中我的工作線程基本上都處於阻塞狀態(以上截圖並沒有體現,進程26028是正常運行時我截的圖)。那么為什么GC這么耗資源呢?一開始我認為是哪一個資源忘記釋放了,於是我將打開的字節流、socket資源等都確認關閉了一遍。可是重新運行程序4、5個小時之后依然出現了同樣的問題。顯然問題並沒有解決。
4、jmap+MAT分析
MAT工具的安裝以及使用,網上有很多資料,這里就不做贅述了。
運行程序,當問題出現時,使用jmap指令將內存dump到文件,命令是:jmap -dump:format=b,file=jmap.bin 26028
.
然后使用MAT工具加載該dump文件即jmap.bin,進行分析。
最后發現有一種數據庫連接對象在內存中積累,占據了將近3G的內存,奇怪的是這段代碼我在很多程序中復用過,都沒有出現過問題。所以我判斷應該是由於高並發造成的問題,數據庫可能承受不了這么大的壓力。
我將存入數據庫的代碼先注釋掉,改成存儲到文件之后,就一切正常了。
好了,bug是找到了,接下來我該去看看高並發的數據庫設計了。
接下來我再介紹調bug過程中用到的幾款工具。
5、jconsole 和 jvisualvm 工具
這兩個工具都是JDK自帶的監控java程序的工具,可以監控本地進程和遠程進程。jvisualvm提供的信息更多一點。
直接在cmd控制台輸入jconsole
和jvisualvm
就可以調出這兩個工具。
jconsole的界面如下:
Jvisualvm (JDK1.6+):界面如下:
6、windows提供的 process explorer 工具
該工具可以到網上下載,它提供比任務管理器更詳細的進程信息,並且可以查看每個進程下的線程: