JVM 調優流程

調優分類說明

jvm調優主要分爲兩個方面,代碼調優和GC調優。
不管哪一種調優,使用top命令查看當前內存和CPU使用狀況是否存在問題java

[root@iZ8vb5a7qagk5piviztthoZ java]# top

檢查是否有異常的%CPU 和%MEM佔用mysql

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                        
904 root      20   0  425268  31168  16400 S   0.3   1.7   0:00.30 tuned

能夠看到,個人系統裏只有一個mysql佔用較高,但也僅爲1.7%的內存佔用web

代碼調優

代碼調優是根據服務器的運行狀態判斷代碼是否存在可優化的部分。
可優化的部分大概分爲死鎖、OOM等問題,可從如下幾個方面入手進行診斷修正spring

jps命令能夠查看全部正在執行的java進程端口號sql

[root@iZ8vb5a7qagk5piviztthoZ ~]# jps
1736 Jps
1627 jar

服務器上只有一個jar包在執行,端口號是1627apache

使用jinfo能夠查看jar包啓動時對應的參數,包含手動設置的參數和默認參數windows

jinfo -flags 1627

從輸出中能夠看到jvm的版本號以及一系列的啓動參數(Non-default VM flags),jdk1.8在沒有設置的狀況下默認使用的GC是parallel+parallel oldtomcat

Attaching to process ID 1627, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.281-b09
Non-default VM flags: -XX:CICompilerCount=2 -XX:InitialHeapSize=29360128 -XX:MaxHeapSize=459276288 -XX:MaxNewSize=153092096 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=9764864 -XX:OldSize=19595264 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps 
Command line:

1. CPU佔用太高

若是CPU有異常狀況則能夠進一步使用 top -p <端口號> 查看具體的內存和CPU佔用springboot

top -p 1627

執行命令會跳轉到以下界面bash

top - 13:33:36 up 49 min,  2 users,  load average: 0.00, 0.00, 0.00
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :   1745.4 total,    191.5 free,    708.6 used,    845.2 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    890.4 avail Mem 

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                        
1627 root      20   0 2396604 121232  16340 S   0.0   6.8   0:07.18 java

而後按住大寫的H查看進程下每一個線程的內存和CPU使用狀況,輸出以下

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                        
1627 root      20   0 2396604 121232  16340 S   0.0   6.8   0:07.26 java                                                           
top - 13:37:08 up 52 min,  2 users,  load average: 0.00, 0.00, 0.00
Threads:  28 total,   0 running,  28 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.3 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
MiB Mem :   1745.4 total,    191.9 free,    708.2 used,    845.3 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.    890.8 avail Mem 

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                        
1627 root      20   0 2396604 121232  16340 S   0.0   6.8   0:00.00 java                                                           
1628 root      20   0 2396604 121232  16340 S   0.0   6.8   0:01.96 java                                                           
1629 root      20   0 2396604 121232  16340 S   0.0   6.8   0:00.30 java                                                           
1630 root      20   0 2396604 121232  16340 S   0.0   6.8   0:00.00 java                                                           
1631 root      20   0 2396604 121232  16340 S   0.0   6.8   0:00.00 java

找到內存佔用最高的線程的pid轉換爲16進制的tid,例如將1628轉換爲65c獲得0x65c
最後用jstack獲得線程堆棧信息中 65b 這個線程所在行的後面10行,從堆棧中能夠發現致使cpu飆高的調用方法

jstack 1627|grep -A 10 65c

該命令爲查看進程號爲1627下的線程號爲1628的線程信息,輸出以下

"DestroyJavaVM" #27 prio=5 os_prio=0 tid=0x00007f5a5800a800 nid=0x65c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-2" #26 prio=5 os_prio=0 tid=0x00007f5a589ba800 nid=0x692 waiting on condition [0x00007f5a295bc000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.demo.DemoApplication$1.run(DemoApplication.java:19)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-Acceptor" #25 daemon prio=5 os_prio=0 tid=0x00007f5a5899b000 nid=0x691 runnable [0x00007f5a298bd000]
   java.lang.Thread.State: RUNNABLE
基於此能夠根據線程信息進行問題的代碼定位

2. 內存佔用太高

jmap命令用來查看進程內存信息,實例個數以及佔用內存大小

[root@iZ8vb5a7qagk5piviztthoZ ~]jmap -histo 1627 >/java/log.txt

日誌文件將會被輸出到/java/目錄下的log.txt文件中,文件內容以下

num     #instances         #bytes  class name
----------------------------------------------
   1:         31296        3094848  [C
   2:          5656        1702416  [I
   3:          3286         769520  [B
   4:         30328         727872  java.lang.String
   5:          7967         701096  java.lang.reflect.Method
   6:          5920         654416  java.lang.Class
   7:         18707         598624  java.util.concurrent.ConcurrentHashMap$Node
   8:          6757         384992  [Ljava.lang.Object;
   9:          7355         294200  java.util.LinkedHashMap$Entry
  10:          3298         279664  [Ljava.util.HashMap$Node;
  11:           110         237408  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  12:          6281         200992  java.util.HashMap$Node
  13:         11832         189312  java.lang.Object
  14:          3183         178248  java.util.LinkedHashMap
  15:          7543         170280  [Ljava.lang.Class;
  16:          1602         115344  java.lang.reflect.Field
  17:           811          97320  org.springframework.boot.loader.jar.JarEntry
  18:          1196          96192  [Ljava.util.WeakHashMap$Entry;
  19:          1994          95712  org.springframework.util.ConcurrentReferenceHashMap$SoftEntryReference
  20:          1668          80064  java.util.HashMap
  21:           908          72640  java.lang.reflect.Constructor
  22:          1235          69160  java.lang.invoke.MemberName
  23:          1316          63168  org.springframework.core.ResolvableType
  24:          1815          58080  java.lang.ref.ReferenceQueue
  25:           926          55480  [Ljava.lang.reflect.Method;
  26:          1276          51040  java.lang.ref.SoftReference
  27:           890          49840  java.lang.Class$ReflectionData
  28:           778          49792  org.springframework.boot.loader.jar.JarFileWrapper
  29:          1202          48080  java.lang.ref.Finalizer
  30:          1008          44992  [Ljava.lang.String;
  31:          1096          43840  java.lang.invoke.MethodType

其中
num:序號
instances:實例數量
bytes:佔用空間大小
class name:類名稱
[C is a char[],[S is a short[],[I is a int[],[B is a byte[],[[I is a int[][]

因爲我在測試服務器只跑了一個計數器的測試程序,因此不存在高內存佔用狀況,打印出來的都是springboot內部的類,若是有高內存佔用則能夠看出是哪一個類佔用了大量的內存

也能夠用jmap -dump命令導出文件後用windows下的可視化工具jvisualvm進行分析,查看內存佔用較高的類

[root@iZ8vb5a7qagk5piviztthoZ java]#jmap -dump:format=b,file=java_pargram.hprof 1627
Dumping heap to /java/java_pargram.hprof ...
Heap dump file created

jmap還有一個參數 heap能夠打印進程號對應的應用的堆信息,查看實時的堆數據

jmap -heap 1627

打印出的堆信息詳細的描述了堆的當前利用狀況

Attaching to process ID 1627, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.281-b09

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 459276288 (438.0MB)
   NewSize                  = 9764864 (9.3125MB)
   MaxNewSize               = 153092096 (146.0MB)
   OldSize                  = 19595264 (18.6875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 8847360 (8.4375MB)
   used     = 2021016 (1.9273910522460938MB)
   free     = 6826344 (6.510108947753906MB)
   22.843153211805557% used
Eden Space:
   capacity = 7864320 (7.5MB)
   used     = 1289280 (1.22955322265625MB)
   free     = 6575040 (6.27044677734375MB)
   16.39404296875% used
From Space:
   capacity = 983040 (0.9375MB)
   used     = 731736 (0.6978378295898438MB)
   free     = 251304 (0.23966217041015625MB)
   74.43603515625% used
To Space:
   capacity = 983040 (0.9375MB)
   used     = 0 (0.0MB)
   free     = 983040 (0.9375MB)
   0.0% used
tenured generation:
   capacity = 19595264 (18.6875MB)
   used     = 11137984 (10.62200927734375MB)
   free     = 8457280 (8.06549072265625MB)
   56.84018342391305% used

3. 死鎖

用jstack加進程id查找死鎖

jstack 1627

該命令會打印出全部的線程信息

2021-02-13 13:27:07
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.281-b09 mixed mode):

"Attach Listener" #28 daemon prio=9 os_prio=0 tid=0x00007f5a34002000 nid=0x6fd waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #27 prio=5 os_prio=0 tid=0x00007f5a5800a800 nid=0x65c waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Thread-2" #26 prio=5 os_prio=0 tid=0x00007f5a589ba800 nid=0x692 waiting on condition [0x00007f5a295bc000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.example.demo.DemoApplication$1.run(DemoApplication.java:19)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-Acceptor" #25 daemon prio=5 os_prio=0 tid=0x00007f5a5899b000 nid=0x691 runnable [0x00007f5a298bd000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:424)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:252)
        - locked <0x00000000e51861a0> (a java.lang.Object)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:469)
        at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:71)
        at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:106)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-ClientPoller" #24 daemon prio=5 os_prio=0 tid=0x00007f5a5897b800 nid=0x690 runnable [0x00007f5a299be000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000e51863d8> (a sun.nio.ch.Util$3)
        - locked <0x00000000e51863e8> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000e5186390> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:711)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-10" #23 daemon prio=5 os_prio=0 tid=0x00007f5a5893f000 nid=0x68f waiting on condition [0x00007f5a29abf000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-9" #22 daemon prio=5 os_prio=0 tid=0x00007f5a5893d000 nid=0x68e waiting on condition [0x00007f5a29bc0000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-8" #21 daemon prio=5 os_prio=0 tid=0x00007f5a5893b800 nid=0x68d waiting on condition [0x00007f5a29cc1000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-7" #20 daemon prio=5 os_prio=0 tid=0x00007f5a584da800 nid=0x68c waiting on condition [0x00007f5a29dc2000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-6" #19 daemon prio=5 os_prio=0 tid=0x00007f5a584d9000 nid=0x68b waiting on condition [0x00007f5a29ec3000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-5" #18 daemon prio=5 os_prio=0 tid=0x00007f5a584d7000 nid=0x68a waiting on condition [0x00007f5a29fc4000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-4" #17 daemon prio=5 os_prio=0 tid=0x00007f5a584d5800 nid=0x689 waiting on condition [0x00007f5a2a0c5000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-3" #16 daemon prio=5 os_prio=0 tid=0x00007f5a58573000 nid=0x688 waiting on condition [0x00007f5a2a1c6000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-2" #15 daemon prio=5 os_prio=0 tid=0x00007f5a58571800 nid=0x687 waiting on condition [0x00007f5a2a2c7000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-exec-1" #14 daemon prio=5 os_prio=0 tid=0x00007f5a58570000 nid=0x686 waiting on condition [0x00007f5a2a3c8000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000e51865a8> (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.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:108)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"http-nio-8080-BlockPoller" #13 daemon prio=5 os_prio=0 tid=0x00007f5a583a5000 nid=0x685 runnable [0x00007f5a2a4c9000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000e51879d0> (a sun.nio.ch.Util$3)
        - locked <0x00000000e51879e0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000e5187988> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:313)

"container-0" #12 prio=5 os_prio=0 tid=0x00007f5a588f7800 nid=0x681 waiting on condition [0x00007f5a2a7ca000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at org.apache.catalina.core.StandardServer.await(StandardServer.java:570)
        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer$1.run(TomcatWebServer.java:197)

"Catalina-utility-2" #11 prio=1 os_prio=0 tid=0x00007f5a58918800 nid=0x680 waiting on condition [0x00007f5a2a8cb000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ee3f8748> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"Catalina-utility-1" #10 prio=1 os_prio=0 tid=0x00007f5a58912000 nid=0x67f waiting on condition [0x00007f5a4812c000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ee3f8748> (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:1074)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f5a580e1800 nid=0x663 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f5a580de800 nid=0x662 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f5a580dc800 nid=0x661 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f5a580db000 nid=0x660 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f5a580a4800 nid=0x65f in Object.wait() [0x00007f5a48c20000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000edcb7520> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x00000000edcb7520> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f5a580a0000 nid=0x65e in Object.wait() [0x00007f5a48d21000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000edcb76d8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000edcb76d8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=0 tid=0x00007f5a58096800 nid=0x65d runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007f5a580e4800 nid=0x664 waiting on condition 

JNI global references: 1227
"Thread-1" 線程名
prio=5 優先級=5
tid=0x000000001fa9e000 線程id
nid=0x2d64 線程對應的本地線程標識nid
java.lang.Thread.State: BLOCKED 線程狀態

若是存在死鎖的話在信息中會有以下的相應提示
image.png
提示中會詳細說明死鎖的位置和緣由

GC調優

使用jstat查看堆內存各部分的使用量
jstat [-命令選項] [vmid] [間隔時間(毫秒)] [查詢次數]
垃圾回收統計的使用方法
jstat -gc <pid>

jstat -gc 1627

打印內容以下:

S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
960.0  960.0  714.6   0.0    7680.0   2923.2   19136.0    10876.9   30720.0 28678.1 4096.0 3661.3     34    0.102   1      0.021    0.123
S0C:第一個倖存區的大小,單位KB
S1C:第二個倖存區的大小
S0U:第一個倖存區的使用大小
S1U:第二個倖存區的使用大小
EC:伊甸園區的大小
EU:伊甸園區的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法區大小(元空間)
MU:方法區使用大小
CCSC:壓縮類空間大小
CCSU:壓縮類空間使用大小
YGC:年輕代垃圾回收次數
YGCT:年輕代垃圾回收消耗時間,單位s
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間,單位s
GCT:垃圾回收消耗總時間,單位s

JVM運行狀態評估
年輕代對象增加的速率能夠執行命令

jstat -gc 1627 1000 10 (每隔1秒執行1次命令,共執行10次)

年輕代對象增加的速率
經過觀察EU(eden區的使用)來估算每秒eden大概新增多少對象,若是系統負載不高,能夠把頻率1秒換成1分鐘,甚至10分鐘來觀察總體狀況。注意,通常系統可能有高峯期和平常期,因此須要在不一樣的時間分別估算不一樣狀況下對象增加速率。

Young GC的觸發頻率和每次耗時
經過運行時間/Young GC的觸發總數和YGCT/YGC兩個公式能夠算出young GC的觸發頻率和每次耗時。
經過這兩個參數能夠知道年輕代對象增加速率,根據結果咱們大概就能知道系統大概多久會由於Young GC的執行而卡頓多久。

每次Young GC後有多少對象存活和進入老年代
這個由於以前已經大概知道Young GC的頻率,假設是每5分鐘一次,那麼能夠執行命令 jstat -gc pid 300000 10 ,觀察每次結果eden,survivor和老年代使用的變化狀況,在每次gc後eden區使用通常會大幅減小,survivor和老年代都有可能增加,這些增加的對象就是每次Young GC後存活的對象,同時還能夠看出每次Young GC後進去老年代大概多少對象,從而能夠推算出老年代對象增加速率

Full GC的觸發頻率和每次耗時
知道了老年代對象的增加速率就能夠推算出Full GC的觸發頻率了,Full GC的每次耗時能夠用公式FGCT/FGC 計算得出。

得出以上結論後,以儘可能減小full gc,儘可能讓對象在young gc的時候被幹掉的原則,根據內存模型調整eden區和old的大小比例來進行jvm優化
image.png

ps:還能夠經過打印GC日誌的方式查看分析GC,進行問題定位 GC日誌打印參數 對應的參數列表 -XX:+PrintGC 輸出GC日誌 -XX:+PrintGCDetails 輸出GC的詳細日誌 -XX:+PrintGCTimeStamps 輸出GC的時間戳(以基準時間的形式) -XX:+PrintGCDateStamps 輸出GC的時間戳(以日期的形式,如 2013-05-04T21:53:59.234+0800) -XX:+PrintHeapAtGC 在進行GC的先後打印出堆的信息 -Xloggc:../logs/gc.log 日誌文件的輸出路徑
相關文章
相關標籤/搜索