Java服務器內存太高&CPU太高問題排查

1、內存太高

一、內存太高通常有兩種狀況:內存溢出和內存泄漏java

(1)內存溢出:程序分配的內存超出物理機的內存大小,致使沒法繼續分配內存,出現OOM報錯數組

(2)內存泄漏:再也不使用的對象一直佔據着內存不釋放,致使這塊內存浪費掉,長此以往,內存泄漏的對象堆積起來,也會致使物理機的內存被耗盡,出現OOM報錯服務器

二、內存太高的檢測辦法:一般咱們的Java服務器部署在Linux機器上面,能夠經過jvm自帶的命令進行一些檢測eclipse

(1)查看對象的數目和佔用內存大小jvm

①參數爲Java程序的進程號,將結果導出到指定目錄中,工具

jmap -histo:live <進程號> > <導出目錄+文件名>

②示例以下,能夠看到程序中各個對象所佔用內存的狀況,根據佔用字節數大小降序顯示,這裏只能看出哪些對象佔用內存高,可是還不能具體定位到問題代碼,須要進一步排查測試

③一些特殊的標識的含義spa

  • [C 表示char[],通常與String對象相關,由於String其實就是基於char數組實現的
  • [S 表示short[]
  • [I 表示int[]
  • [B 表示byte[]
  • [II 表示int[][]
 num     #instances         #bytes  class name
----------------------------------------------
   1:        585152       75635896  [C
   2:         66541       71446496  [B
   3:       1141734       36535488  java.util.HashMap$Entry
   4:        176622       26086840  <constMethodKlass>
   5:        176622       24034208  <methodKlass>
   6:         17717       19584560  <constantPoolKlass>
   7:        174454       18375128  [Ljava.util.HashMap$Entry;
   8:        571222       13709328  java.lang.String
   9:        832783       13324528  java.lang.Integer
  10:         17717       13198840  <instanceKlassKlass>
  11:         15092       11237440  <constantPoolCacheKlass>
  12:         46779       10429728  [I
  13:        191501        7660040  java.util.LinkedHashMap$Entry
  14:         12599        6567592  <methodDataKlass>
  15:        113526        6357456  java.util.HashMap
  16:        197998        6335936  java.util.Hashtable$Entry

(2)若是須要進一步定位問題代碼,那麼就須要把Java程序的內存鏡像導出,再具體分析了,經過以下命令導出程序的內存鏡像線程

jmap -dump:format=b,file=<導出目錄+文件名> <進程號>

(3)下載Memory Analyzer工具來分析內存鏡像3d

http://www.eclipse.org/mat/

(4)打開軟件後,File-->Open Heap Dump...,打開剛纔導出的鏡像文件,選擇Leak Suspects Report,Finish,進入分析頁面

  • Histogram:列表展現出內存中的對象數目和佔用內存大小
  • Dominator Tree:列表展現出程序中每一個線程中的對象數目和佔用內存大小
  • Top Consumers:圖表展現出每一個線程的對象數目和佔用內存大小
  • Top Components:圖表展現出內存中的對象數目和佔用內存大小
  • Leak Suspects:這個是最經常使用的,會自動檢測分析內存異常的緣由

  右鍵對象-->show objects by class能夠查看對象的具體狀況
    by incomming reference:顯示引用該對象/線程的其餘對象
    by outgoing reference:顯示當前對象/線程引用的其餘對象

(5)點擊Leak Suspects,程序會分析出可能存在內存問題的地方,繼續點擊Detail能夠看到具體有哪些對象和線程,接下來就要根據具體狀況具體分析了

 2、CPU太高(Windows系統)

一、當程序發現CPU太高的狀況時,可使用Windows系統的Process Explorer工具來找到CPU高消耗的線程,因此須要在Windows機器上面搭建好服務器的測試環境,儘可能模擬出線上CPU飆升的狀況

二、模擬好環境後,經過任務管理器,在進程一欄中找到Java程序的進程號

三、下載Process Explorer工具

https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer

四、打開工具後,根據剛纔的進程號找到進程

五、而後右鍵-->Properties,再選擇Threads選項卡,點進CPU排序,能夠找到消耗CPU最多的那個線程的十進制線程ID

3、CPU太高(Linux系統)

一、咱們的Java服務器通常都是部署在Linux系統上面的,當出現CPU太高時,能夠先用top命令找到CPU太高的Java進程的進程號

二、而後進一步使用進程號來查看線程的狀況

top -H -p <PID>

4、分析CPU問題

一、上面咱們找到了CPU太高的具體十進制線程號,使用科學計算器,將十進制的線程號轉成十六進制,好比493620-->78834

二、到此已經拿到了可能出問題的進程號和線程號,接下來使用jvm內置的命令來導出Java的堆棧信息

jstack -l <進程號> > <導出目錄+文件名>

三、打開導出的堆棧信息,並全文搜索剛剛拿到的十六進制的線程號,就能夠找到出問題的代碼具體位置了

5、經常使用的分析工具

一、查看Java進程中GC的狀況,能夠看到新生代老年代等的GC次數和GC時間等參數

jstat -gc <PID>

二、待補充

相關文章
相關標籤/搜索