共计 24781 个字符,预计需要花费 62 分钟才能阅读完成。
调优分类阐明
jvm 调优次要分为两个方面,代码调优和 GC 调优。
无论哪种调优,应用 top 命令查看以后内存和 CPU 应用状况是否存在问题
[root@iZ8vb5a7qagk5piviztthoZ java]# top
查看是否有异样的 %CPU 和 %MEM 占用
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% 的内存占用
代码调优
代码调优是依据服务器的运行状态判断代码是否存在可优化的局部。
可优化的局部大略分为死锁、OOM 等问题,可从以下几个方面动手进行诊断修改
jps 命令能够查看所有正在执行的 java 过程端口号
[root@iZ8vb5a7qagk5piviztthoZ ~]# jps
1736 Jps
1627 jar
服务器上只有一个 jar 包在执行,端口号是 1627
应用 jinfo 能够查看 jar 包启动时对应的参数,蕴含手动设置的参数和默认参数
jinfo -flags 1627
从输入中能够看到 jvm 的版本号以及一系列的启动参数(Non-default VM flags),jdk1.8 在没有设置的状况下默认应用的 GC 是 parallel+parallel old
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 占用
top -p 1627
执行命令会跳转到如下界面
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 线程状态
如果存在死锁的话在信息中会有如下的相应提醒
提醒中会具体阐明死锁的地位和起因
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 优化
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 日志文件的输入门路