JVM及Java監控原理與實踐

簡介

主要是介紹一下對運行Java程序的一些跟蹤,以及對JVM內存等方面進行運維的一些方法。java

反解析class文件的工具使用

  • 通常使用jd-gui工具進行反編譯class文件
  • 有些jd-gui沒法反編譯的class,能夠使用luyten工具進行反編譯

Java進程分析命令介紹

jps

用於獲取全部的JVM進程信息,相似於linux的ps命令linux

//輸出進程號與執行的主類名(jar包名)
jps -l 

結果以下:

30352
20708 sun.tools.jps.Jps
6876 mtex-config-0.0.1-SNAPSHOT.jar
複製代碼

jstat

用於監控java進程內部各種運行狀態信息的工具,能夠監控本地或遠程虛擬機類裝載、內存、垃圾回收等信息。spring

//監控GC狀況 間隔1000毫秒執行1次 執行5次
jstat -gc 6876 1000 5

執行結果以下:

C:\Users\dell>jstat -gc 6876 1000 5
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
13824.0 15872.0 13804.6  0.0   140288.0 129170.6  102400.0   19730.9   54528.0 52078.9 7168.0 6684.3     10    0.143   2      0.172    0.315
13824.0 15872.0 13804.6  0.0   140288.0 129170.6  102400.0   19730.9   54528.0 52078.9 7168.0 6684.3     10    0.143   2      0.172    0.315
13824.0 15872.0 13804.6  0.0   140288.0 129170.6  102400.0   19730.9   54528.0 52078.9 7168.0 6684.3     10    0.143   2      0.172    0.315
13824.0 15872.0 13804.6  0.0   140288.0 129170.6  102400.0   19730.9   54528.0 52078.9 7168.0 6684.3     10    0.143   2      0.172    0.315
13824.0 15872.0 13804.6  0.0   140288.0 129170.6  102400.0   19730.9   54528.0 52078.9 7168.0 6684.3     10    0.143   2      0.172    0.315

結果說明:

S0C 年輕代s0區容量
S1C 年輕代s1區容量
S0U 年輕代s0區使用量
S1U 年輕代s1區使用量
EC  年輕代eden區容量
EU	年輕代eden區容量
OC  老年代容量
OU  老年代使用量
MC  元空間容量
MU  元空間使用量
CCSC 壓縮類空間容量
CCSU 壓縮類空間使用大小
YGC  從應用程序啓動到採樣時年輕代中gc次數
YGCT 從應用程序啓動到採樣時年輕代中gc時間
FGC  從應用程序啓動到採樣時全gc次數
FGCT 從應用程序啓動到採樣時全gc時間
GCT  從應用程序啓動到採樣時gc用的總時間(s)

複製代碼

s0和s1中必然有一個的使用空間爲0,用於複製交換apache

JDK 1.8如下MC/MU指標爲PC/PU。(jdk1.8使用元空間替換了永久代)tomcat

經過參數的不一樣,能夠進行某些方面的重點信息關注bash

選項 做用
-class 監視類裝載、卸載數量、總空間以及類裝載所耗費的時間
-gc 監視Java堆情況,包括Eden區、兩個survivor區、老年代、元空間的容量、已用空間、GC時間合計等信息
-gccapacity 監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用到的最大、最小空間
-gcutil 監視內容與-gc基本相同,但輸出主要關注已使用空間佔總空間的百分比
-gccause 與-gcutil功能同樣,可是會額外輸出致使上一次GC產生的緣由
-gcnew 監視新生代GC情況
-gcnewcapacity 監視內容與-gcnew基本相同,輸出主要關注使用到的最大、最小空間
-gcold 監視老年代情況
-gcoldcapacity 監視內容與-gcold基本相同,輸出主要關注用到的最大、最小空間
-gcmetacapacity 輸出元數據用到的最大、最小空間
-compiler 輸出JIT編譯器編譯過的方法、耗時等信息
-printcompilation 輸出已經被JIT編譯的方法

jmap

能夠用來查詢堆中的實例或者進行堆dump等。app

//顯示堆中對象統計信息,包括類、實例數、合計佔用量

jmap -histo 6876 > a.txt


 num     #instances #bytes class name
----------------------------------------------
   1:        652896       67501960  [B
   2:        493614       47624832  [C
   3:         54335       17164304  [I
   4:        126862        3044688  java.lang.String
   5:         28292        2489696  java.lang.reflect.Method
   6:         27951        1786648  [Ljava.lang.Object;
   7:         21992        1334608  [Lorg.springframework.boot.context.properties.source.ConfigurationPropertyName$ElementType;
   8:         18122        1311816  [Ljava.util.HashMap$Node;
   9:         32653        1306120  java.util.LinkedHashMap$Entry
  10:         10985        1219992  java.lang.Class
  11:         35321        1130272  java.util.concurrent.ConcurrentHashMap$Node
  12:         17251         966056  java.util.LinkedHashMap
  13:         29707         950624  java.util.HashMap$Node
  14:         45305         908512  [Ljava.lang.Class;
  15:           512         724368  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  16:         13340         640320  java.util.HashMap
  17:          7763         604160  [S
  18:          7641         550152  java.lang.reflect.Field
  ...

複製代碼

執行此命令須要將輸出重定向到文件裏,不然會有幾千上萬行運維

//生成堆快照信息
jmap -dump:format=b,file=heap.hprof 6876

複製代碼

堆內存快照信息

jstack

用於生成java的線程快照信息eclipse

jstack -l 6876 > threadDump.txt

執行結果:


2020-03-23 16:51:55
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.65-b01 mixed mode):

"DestroyJavaVM" #58 prio=5 os_prio=0 tid=0x0000000060c4a000 nid=0x6618 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
	- None

"http-nio-8601-Acceptor" #32 daemon prio=5 os_prio=0 tid=0x0000000060c49800 nid=0x824 runnable [0x00000000648de000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
	- locked <0x00000000e0c3b670> (a java.lang.Object)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:463)
	at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:73)
	at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95)
	at java.lang.Thread.run(Thread.java:745)
	
...

複製代碼

此命令也最好能夠重定向到文件,輸出結果較多工具

Java VisualVM工具介紹

VisualVM是目前爲止JDK發佈功能最強大的運行監控故障處理程序。

工具路徑

在jdk路徑的bin目錄下,jvisualvm.exe

監控本地項目

雙擊工具,進入主界面,左側便可看到本地的java進程,雙擊便可在右側查看內容。

本地項目

監控遠程項目

執行java -jar啓動命令時候加入如下參數,hostname爲遠程的主機名,port使用一個沒被佔用的端口

-Djava.rmi.server.hostname=xxxxxx -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.managementote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

複製代碼

雙擊左側遠程,添加主機IP,遠程下會出現對應的主機,雙擊選擇添加JMX鏈接,彈框輸入端口。點擊肯定,便可進行遠程監控。

本地項目

總體狀況監控

總體狀況

線程監控

線程

對象狀況監控

對象

Eclipse Memory Analyzer工具安裝使用

一、安裝

eclipse -->help --> eclipse marketplace,輸入memory,搜索出具體的插件,進行安裝。

內存分析工具安裝

二、使用

使用jmap命令或者經過vusal工具dump下內存快照,拖進eclipse便可。

對象列表

實例排序

可疑報告

經常使用的JVM配置參數

參數名稱 含義 默認值
-Xms 初始堆大小 物理內存的1/64
-Xmx 最大堆大小 物理內存的1/4
-XX:NewSize 年輕代的初始大小
-XX:MaxNewSize 年輕代的最大值
-Xmn 年輕代的大小,若是經過-Xmn來配置新生代的內存大小,那麼-XX:newSize = -XX:MaxNewSize = -Xmn
-XX:NewRatio 年輕代與老年代的比例 4 表示 年輕代與老年代比例爲 1:4
-XX:SurvivorRatio 兩個Survivor區與eden的比例 8 表示兩個survivor:eden爲 2:8

查看本機默認參數命令

java -XX:+PrintFlagsFinal > E:\ab.txt
複製代碼

如何查看高CPU佔用的線程

示例:

一、找到java的進程

C:\Users\dell>jps -l

24352 cn.mastercom.MtexConfigApplication
30352
43508 sun.tools.jps.Jps
複製代碼

二、對具體進程進行線程dump

C:\Users\dell\Desktop>jstack -l 24352 > thread.txt
複製代碼

三、使用工具查看佔用高的線程ID

linux經過top 命令進程查詢

top -H -p 24352

top - 16:44:36 up 74 days,  1:22,  1 user,  load average: 0.52, 0.39, 0.39
Threads:  30 total,   0 running,  30 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1882752 total,    92228 free,   980456 used,   810068 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   706556 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                       
17063 root      20   0 2525764 138224  12788 S  0.0  7.3   0:00.00 java                                                                                          
17065 root      20   0 2525764 138224  12788 S  0.0  7.3   0:02.62 java                                                                                          
17067 root      20   0 2525764 138224  12788 S  0.0  7.3   0:05.73 java                                                                                          
17068 root      20   0 2525764 138224  12788 S  0.0  7.3   0:00.00 java                                                                                          
17069 root      20   0 2525764 138224  12788 S  0.0  7.3   0:00.00 java                                                                                          
17070 root      20   0 2525764 138224  12788 S  0.0  7.3   0:00.00 java                                                                                          
17071 root      20   0 2525764 138224  12788 S  0.0  7.3   0:07.06 java                                                                                          
17072 root      20   0 2525764 138224  12788 S  0.0  7.3   0:01.59 java                                                                                          
17073 root      20   0 2525764 138224  12788 S  0.0  7.3   0:00.00 java      

能夠看到CPU佔用高的百分比
複製代碼

windwos能夠使用ProcessExplorer軟件進行查看

線程分析

四、將線程ID轉爲16進制,由於線程dump的線程ID是使用16進制的。

43404 --> A98C
複製代碼

五、去以前dump的線程映像中查看對應線程

"Catalina-utility-1" #17 prio=1 os_prio=-2 tid=0x000000006130b000 nid=0xa98c waiting on condition [0x000000005e7be000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000e358e9a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1088)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
	- None
複製代碼

若是是本身寫的代碼,能夠從上面查看到具體的問題。

相關文章
相關標籤/搜索