一句話總結:從問題現象爲入口,歸結爲3類問題進行定位分析:內存滿、CPU高、線程阻塞。java
首先先介紹下jvisualvm這款jdk自帶的性能工具。一般咱們要定位哪塊代碼性能差,耗時久,最原始的辦法就是在各個方法先後日誌打印時間戳並計算耗時,這種方法很繁瑣,一般要加不少日誌屢次部署才能定位到,我一開始也是這麼搞的。而使用jvisualvm工具則能夠直接查看整個業務代碼調用鏈中各個方法的耗時及佔比,直接就能定界出是哪一個方法性能差,耗時久。linux
操做步驟:點擊抽樣器頁籤,點擊CPU抽樣,前臺操做觸發代碼執行,操做完點擊中止,再點擊快照。在快照頁點擊搜索按鈕,輸入代碼入口方法名搜索,結果見下圖。架構
咱們來分析下下圖,RegionNorthbound.createRegion是北向入口方法,總耗時見右側5.298秒,其調用了RegionServiceImpl.createRegion方法,耗時4.093秒,那麼相減就是RegionNorthbound.createRegion方法自己的耗時。jvm
RegionServiceImpl.createRegion方法調用了CommonDao.saveEntity和RegionServiceImpl.checkRepeat方法,分別耗時0.998秒和0.094秒。能夠直觀查看是調用的哪一個方法耗時久,性能差。整個方法調用鏈的耗時都可查看。工具
這在大型系統中很是有用。大型系統中一般業務由業務部門開發,平臺由平臺部門開發,只提供jar包給業務部門使用。那麼當測試出性能問題時,首先要定界出是業務的問題仍是平臺的問題,再轉給對應部門去修改。業務開發不知道平臺的實現,沒法查看修改其代碼,更不用說去加日誌。固經過此工具能夠快速定界出問題責任主體。性能
固然jvisualvm除了查看代碼調用鏈耗時,實時監控CPU、內存、線程數,線程dump、內存dump等功能都很是好用。學習
下面開始按問題分類進行定位分析。測試
一:內存問題spa
問題現象:後臺報錯,前臺提示異常或500錯誤。線程
定位:後臺報錯的定位思路很明確了,查看日誌,這裏分兩類異常:1、java.lang.OutOfMemoryError: PermGen space異常,此爲方法區內存溢出,方法區用來存放class代碼,一般解決辦法就是調大jvm permSize參數值;2、java.lang.OutOfMemoryError: heap space異常,比較常見的堆內存溢出。固然也能夠調大jvm參數來解決,但如果不恰當代碼引發的,首先檢查下本身寫的代碼,看哪裏建立了大量對象。若檢查不出來,則使用jmap或jvisualvm導出內存快照。
分析下圖heap dump,這裏又分兩種狀況,若左側佔內存大的類名爲com.**.User這種本身定義的業務對象,那在代碼中搜索下此類名就能定位到哪裏建立了大量此對象。若爲String、Integer這種基本類型的對象,則可使用Eclipse Memory Analyer此類工具進一步分析,能夠查看內存大對象的線程堆棧,便可查看代碼調用方法。
二:CPU問題
問題現象:前臺顯示卡頓,響應時間長,linux top查看cpu使用率很是高
定位步驟:
一、使用top查看進程pid,java系統一般進程名就叫java
二、使用top -H -p pid查看進程中各線程的CPU使用狀況,找出最佔CPU的線程pid,注意這裏其實就是tid
三、經過步驟2咱們知道是哪一個線程佔CPU了,使用jstack pid打印線程堆棧,查看該線程的代碼調用方法
四、將步驟2線程tid轉換爲16進制,由於jstack打印出來的threaddump中tid爲16進制,而後在threaddump中搜索,便可找到線程堆棧,這裏30725轉換爲16進制就是7805
這裏有個狀況要特別說明,若是步驟4查看的佔用CPU的線程爲java gc線程,一般是因爲內存快滿才致使jvm頻繁gc,進而致使CPU高。固此種狀況得按上面提到的內存問題去定位解決。Java架構交流學習圈:874811168 面向1-3年經驗 Java開發人員 幫助突破瓶頸 提高思惟能力
三:線程問題
問題現象1:請求響應時間長,性能測試TPS/QPS上不去,查看CPU佔用又不高
問題現象2:請求響應直接超時,後臺線程相互死鎖
定位:線程問題一般打印一次threaddump是看不出問題的,要多打印幾回對比才能看出問題。建議使用jvisualvm線程頁籤實時查看線程狀態。查看指定業務線程狀態,若長時間處於wait或block狀態,則可確認該問題是因爲線程阻塞引發的。查看線程堆棧可查看是調用哪一個方法時阻塞的。死鎖問題也是相似定位,線程堆棧裏會提示在等待哪一個線程釋放lock,而有兩個線程互相等待即會死鎖。
備忘:
jvisualvm鏈接遠程jvm,遠程jvm添加啓動參數: