Java生產環境下問題排查


在生產環境中,我們無法通過斷點調試、新增log、可視化工具去立馬查看當前的運行狀態和拿到錯誤信息,此時,借助Java自帶的命令行工具以及相關dump分析工具以及一些小技巧,可以大大提升我們排查問題的效率

運行參數

下面會列出一些常用且非常有效的命令以及參數來查看運行時Java程序的信息,從而輔助你了解程序運行狀態。還有大量可用的功能由其他參數提供,自行參閱oracle文檔

查看JVM參數

jps -l 查看所有正在運行的Java程序,同時顯示啟動類類名,獲取到PID

1 4706 org.apache.catalina.startup.Bootstrap
2 5023 sun.tools.jps.Jps
 

jinfo -flags PID 查看運行時進程參數與JVM參數

1 Attaching to process ID 28987, please wait...
2 Debugger attached successfully.
3 Server compiler detected.
4 JVM version is 25.171-b11
5 Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=132120576 -XX:MaxHeapSize=2092957696 -XX:MaxNewSize=697303040 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=44040192 -XX:OldSize=88080384 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
6 Command line:  -Dspring.config.location=application.properties -Dspring.profiles.active=staging

java -XX:+PrintFlagsFinal -version 查看當前虛擬機默認JVM參數

查看即時GC狀態

jstat -gc PID 1000 10 每秒查看一次gc信息,共10次

輸出比較多的參數,每個字段的解釋參看 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

1  S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
2 512.0  512.0   15.3   0.0    4416.0   1055.2   11372.0     7572.5   14720.0 14322.5 1664.0 1522.8     40    0.137   8      0.039    0.176

期間可能碰到提示sun.jvm.hotspot.runtime.VMVersionMismatchException: Supported versions are 24.181-b01. Target VM is 25.171-b11的問題,原因在於安裝了多個版本,使用whichls -l可簡介定位到與當前執行Java程序相同的Java版本

錯誤排查

內存問題

內存泄露導致OOM?內存占用異常的高?這是生產環境常常出現的問題,Java提供dump文件供我們對內存里發生過的事情進行了記錄,我們需要借助一些工具從中獲取有價值的信息。

導出Dump文件

  1. 提前對Java程序加上這些參數印dump文件 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
  2. 對正在運行的程序使用jmapjmap -dump:format=b,file=heap.hprof PID

分析Dump文件

如果Dump文件不太大的話,可以傳到 http://heaphero.io/index.jsp 來分析

文件比較大,且想進行更加系統的分析,推薦使用MAT分析,有如下幾種常用查看方式

  1. 首頁中的【Leak Suspects】能推測出問題所在
  2. 點擊【Create a histogram from an arbitrary set of objects】查到所有對象的數量
  3. 右鍵點擊某個對象【Merge Shortest Paths to GC Roots】-> 【exclude all phantom/weak/soft etc. references】能查詢到大量數量的某個對象是哪個GC ROOT引用的

線程問題

任務長時間不退出?CPU 負載過高?很可能因為死循環或者死鎖,導致某些線程一直執行不被中斷,但是不報錯是最煩人的,所以日志里看不到錯誤信息,並且又不能用dump文件分析,因為跟內存無關。這個時候就需要用線程分析工具來幫我們了。

導出jstack文件

使用jstack PID > 文件,如果失敗請加-F參數,如果還失敗請使用Java程序啟動時使用的用戶執行jstack,下面是jstack的部分輸出格式

1       線程名                                                              PID的16進制
2 "http-nio-8080-Acceptor-0" #17 daemon prio=5 os_prio=0 tid=0x00007fac2c4bd000 nid=0x29f4 runnable [0x00007fac192f6000]
3    java.lang.Thread.State: RUNNABLE(tomcat的工作線程正在運行,有NEW/RUNNABLE/BLOCKED/WAITING/TIMED_WATING/TERMINATED狀態)
4     at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
5     at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
6     at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
7     - locked <0x00000000faf845a8> (a java.lang.Object)
8     at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:682)
9     at java.lang.Thread.run(Thread.java:748)

 

jstack的輸出可以看到所有的線程以及他們的狀態,我們就可以看有哪些我們自己創建的正在運行的線程,那很可能就是那個一直在執行的線程了,此時線程名就格外重要了,所以建議創建新線程時指定有意義的線程名。當然,通過PID查找也非常方便。

排查步驟

  1. top 查看到哪個java程序負載高
  2. top -p PID -H 查看該進程所有進程的運行狀態
  3. 記錄下高負載的線程ID,printf "&x" PID轉換成16進制
  4. jstack PID > 文件
  5. 在jstack文件中用轉換成16進制之后的線程ID查詢線程運行堆棧
  6. 從堆棧中了解到線程在執行什么任務,並結合業務與代碼判斷問題所在

轉載

https://www.wangtianyi.top/blog/2018/07/20/javasheng-chan-huan-jing-xia-wen-ti-pai-cha/?utm_source=github&utm_medium=github


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM