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:
若是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
基於此能夠根據線程信息進行問題的代碼定位
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
用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 線程狀態
若是存在死鎖的話在信息中會有以下的相應提示
提示中會詳細說明死鎖的位置和緣由
使用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優化
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 日誌文件的輸出路徑