本文主要研究一下jvm的Stack Memory
/** * -Xss144k */ @Test public void testStackOverflow(){ recursiveInvoke(); } public void recursiveInvoke(){ String uuid = UUID.randomUUID().toString(); recursiveInvoke(); }
异常输出如下:
java.lang.StackOverflowError at java.base/sun.security.provider.ByteArrayAccess.b2iBig64(ByteArrayAccess.java:263) at java.base/sun.security.provider.SHA.implCompressCheck(SHA.java:139) at java.base/sun.security.provider.SHA.implCompress(SHA.java:128) at java.base/sun.security.provider.SHA.implDigest(SHA.java:109) at java.base/sun.security.provider.DigestBase.engineDigest(DigestBase.java:210) at java.base/sun.security.provider.DigestBase.engineDigest(DigestBase.java:189) at java.base/java.security.MessageDigest$Delegate.engineDigest(MessageDigest.java:629) at java.base/java.security.MessageDigest.digest(MessageDigest.java:385) at java.base/sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:245) at java.base/sun.security.provider.NativePRNG$RandomIO.implNextBytes(NativePRNG.java:535) at java.base/sun.security.provider.NativePRNG$NonBlocking.engineNextBytes(NativePRNG.java:318) at java.base/java.security.SecureRandom.nextBytes(SecureRandom.java:741) at java.base/java.util.UUID.randomUUID(UUID.java:150) at com.example.VMStackTest.recursiveInvoke(VMStackTest.java:21)
Xss越大,每个线程的大小就越大,占用的内存越多,能创建的线程就越少;Xss越小,则递归的深度越小,容易出现栈溢出 java.lang.StackOverflowError。减少局部变量的声明,可以节省栈帧大小,增加调用深度。
public void createThreadAsManyAsPossible(){ try{ while (true) { new Thread(new Runnable() { public void run() { try { TimeUnit.HOURS.sleep(1); } catch (InterruptedException e) { } } }).start(); } }catch (Throwable e){ LOGGER.error(e.getMessage(),e); } }
docker run -v /tmp:/tmp --memory=256m -p 8080:8080 / -e JAVA_OPTS='-server -Xmx128m -Xss1m -XX:ParallelGCThreads=4 -XX:ConcGCThreads=4 -XX:+UnlockDiagnosticVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp' / -e PROFILE='default' / demo
[ { "Id": "93ec46e93290f8dc70901680c251dd9faef4a5a283cb6020ec8640fed4001026", "Created": "2019-04-01T02:22:41.007466012Z", //...... "State": { "Status": "exited", "Running": false, "Paused": false, "Restarting": false, "OOMKilled": true, "Dead": false, "Pid": 0, "ExitCode": 137, "Error": "", "StartedAt": "2019-04-01T02:22:41.284627718Z", "FinishedAt": "2019-04-01T02:22:59.192763475Z" }, "Image": "sha256:bbaf9474dd259b8c6afe39cbbccce62bb695b52fda79d8ce3a727be89fcef5c6", //...... ]
可以看到State里头的OOMKilled为true
public void createThreadAsManyAsPossible(){ try{ while (true) { new Thread(new Runnable() { public void run() { try { TimeUnit.HOURS.sleep(1); } catch (InterruptedException e) { } } }).start(); } }catch (Throwable e){ LOGGER.error(e.getMessage(),e); } }
-server -Xmx128m -Xss1m -XX:ParallelGCThreads=4 -XX:ConcGCThreads=4 -XX:+UnlockDiagnosticVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Djava.io.tmpdir=/tmp
不使用docker,直接在本机执行,可以看到如下报错
java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached at java.base/java.lang.Thread.start0(Native Method) ~[na:na] at java.base/java.lang.Thread.start(Thread.java:804) ~[na:na]
/ # jcmd 1 VM.native_memory scale=MB 1: Native Memory Tracking: Total: reserved=1321MB, committed=204MB - Java Heap (reserved=128MB, committed=121MB) (mmap: reserved=128MB, committed=121MB) - Class (reserved=1065MB, committed=46MB) (classes #8234) ( instance classes #7694, array classes #540) (malloc=1MB #19759) (mmap: reserved=1064MB, committed=44MB) ( Metadata: ) ( reserved=40MB, committed=39MB) ( used=38MB) ( free=1MB) ( waste=0MB =0.00%) ( Class space:) ( reserved=1024MB, committed=6MB) ( used=5MB) ( free=0MB) ( waste=0MB =0.00%) - Thread (reserved=36MB, committed=2MB) (thread #36) (stack: reserved=36MB, committed=2MB) - Code (reserved=65MB, committed=11MB) (malloc=1MB #4218) (mmap: reserved=65MB, committed=10MB) - GC (reserved=9MB, committed=7MB) (malloc=5MB #6043) (mmap: reserved=4MB, committed=2MB) - Internal (reserved=4MB, committed=4MB) (malloc=2MB #3454) (mmap: reserved=2MB, committed=2MB) - Symbol (reserved=10MB, committed=10MB) (malloc=7MB #220126) (arena=3MB #1) - Native Memory Tracking (reserved=4MB, committed=4MB) (tracking overhead=4MB)
使用jcmd pid VM.native_memory scale=MB可以查看thread stack的信息,具体在Thread部分,这里显示一共有36个线程,stack的reserved大小为36M
/ # jcmd 1 Thread.print 1: 2019-04-01 10:43:13 Full thread dump OpenJDK 64-Bit Server VM (12+33 mixed mode): Threads class SMR info: _java_thread_list=0x0000562b1182fe30, length=28, elements={ 0x0000562b0ffa5000, 0x0000562b0ffaa000, 0x0000562b0ffdc000, 0x0000562b0ffde800, 0x0000562b0ffe1000, 0x0000562b1003d800, 0x0000562b1016b000, 0x0000562b1017f800, 0x0000562b1141f800, 0x0000562b10a74000, 0x0000562b10b64000, 0x0000562b10fee800, 0x0000562b125d1000, 0x0000562b1040d800, 0x0000562b11983800, 0x0000562b11982000, 0x0000562b10cc7800, 0x0000562b13630800, 0x0000562b13632000, 0x0000562b136f0800, 0x0000562b136e0800, 0x0000562b136e1800, 0x0000562b13621800, 0x0000562b1360c000, 0x0000562b136cd000, 0x0000562b12115000, 0x0000562b11f9e000, 0x0000562b11ff8800 } "Reference Handler" #2 daemon prio=10 os_prio=0 cpu=2.69ms elapsed=31.15s tid=0x0000562b0ffa5000 nid=0xb waiting on condition [0x00007f5cbb576000] java.lang.Thread.State: RUNNABLE at java.lang.ref.Reference.waitForReferencePendingList(java.base@12/Native Method) at java.lang.ref.Reference.processPendingReferences(java.base@12/Reference.java:241) at java.lang.ref.Reference$ReferenceHandler.run(java.base@12/Reference.java:213) "Finalizer" #3 daemon prio=8 os_prio=0 cpu=0.25ms elapsed=31.15s tid=0x0000562b0ffaa000 nid=0xc in Object.wait() [0x00007f5cbb475000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(java.base@12/Native Method) - waiting on <0x00000000f800a840> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(java.base@12/ReferenceQueue.java:155) - locked <0x00000000f800a840> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(java.base@12/ReferenceQueue.java:176) at java.lang.ref.Finalizer$FinalizerThread.run(java.base@12/Finalizer.java:170) "Signal Dispatcher" #4 daemon prio=9 os_prio=0 cpu=0.79ms elapsed=31.14s tid=0x0000562b0ffdc000 nid=0xd runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 cpu=4680.36ms elapsed=31.14s tid=0x0000562b0ffde800 nid=0xe waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE No compile task "C1 CompilerThread0" #6 daemon prio=9 os_prio=0 cpu=2329.95ms elapsed=31.14s tid=0x0000562b0ffe1000 nid=0xf waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE No compile task "Sweeper thread" #7 daemon prio=9 os_prio=0 cpu=71.45ms elapsed=31.13s tid=0x0000562b1003d800 nid=0x10 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Service Thread" #8 daemon prio=9 os_prio=0 cpu=47.53ms elapsed=31.06s tid=0x0000562b1016b000 nid=0x11 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Common-Cleaner" #9 daemon prio=8 os_prio=0 cpu=3.92ms elapsed=31.05s tid=0x0000562b1017f800 nid=0x13 in Object.wait() [0x00007f5cbad6c000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(java.base@12/Native Method) - waiting on <0x00000000f80c1880> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(java.base@12/ReferenceQueue.java:155) - locked <0x00000000f80c1880> (a java.lang.ref.ReferenceQueue$Lock) at jdk.internal.ref.CleanerImpl.run(java.base@12/CleanerImpl.java:148) at java.lang.Thread.run(java.base@12/Thread.java:835) at jdk.internal.misc.InnocuousThread.run(java.base@12/InnocuousThread.java:134) "Catalina-utility-1" #13 prio=1 os_prio=0 cpu=9.33ms elapsed=19.61s tid=0x0000562b1141f800 nid=0x19 waiting on condition [0x00007f5cb93ac000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000ffac03b8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@12/ScheduledThreadPoolExecutor.java:1177) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@12/ScheduledThreadPoolExecutor.java:899) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "Catalina-utility-2" #14 prio=1 os_prio=0 cpu=2.97ms elapsed=19.61s tid=0x0000562b10a74000 nid=0x1a waiting on condition [0x00007f5cb827d000] java.lang.Thread.State: TIMED_WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000ffac03b8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(java.base@12/LockSupport.java:235) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(java.base@12/AbstractQueuedSynchronizer.java:2123) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@12/ScheduledThreadPoolExecutor.java:1182) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(java.base@12/ScheduledThreadPoolExecutor.java:899) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "container-0" #15 prio=5 os_prio=0 cpu=0.16ms elapsed=19.60s tid=0x0000562b10b64000 nid=0x1b waiting on condition [0x00007f5cb817c000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(java.base@12/Native Method) at org.apache.catalina.core.StandardServer.await(StandardServer.java:568) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer$1.run(TomcatWebServer.java:181) "Thread-1" #16 daemon prio=9 os_prio=0 cpu=0.26ms elapsed=19.38s tid=0x0000562b10fee800 nid=0x1c waiting on condition [0x00007f5cb7f25000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fe2f54f0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.LatencyUtils.PauseDetector$PauseDetectorThread.run(PauseDetector.java:85) "SimplePauseDetectorThread_0" #17 daemon prio=9 os_prio=0 cpu=20.21ms elapsed=19.37s tid=0x0000562b125d1000 nid=0x1d waiting on condition [0x00007f5cb7e24000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(java.base@12/Native Method) at java.lang.Thread.sleep(java.base@12/Thread.java:340) at java.util.concurrent.TimeUnit.sleep(java.base@12/TimeUnit.java:446) at org.LatencyUtils.TimeServices.sleepNanos(TimeServices.java:62) at org.LatencyUtils.SimplePauseDetector$SimplePauseDetectorThread.run(SimplePauseDetector.java:116) "NioBlockingSelector.BlockPoller-1" #18 daemon prio=5 os_prio=0 cpu=2.27ms elapsed=17.43s tid=0x0000562b1040d800 nid=0x23 runnable [0x00007f5cba443000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPoll.wait(java.base@12/Native Method) at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@12/EPollSelectorImpl.java:120) at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@12/SelectorImpl.java:124) - locked <0x00000000fb4b21c0> (a sun.nio.ch.Util$2) - locked <0x00000000fb4b1dc8> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(java.base@12/SelectorImpl.java:136) at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:304) "http-nio-8080-exec-1" #19 daemon prio=5 os_prio=0 cpu=0.13ms elapsed=17.42s tid=0x0000562b11983800 nid=0x24 waiting on condition [0x00007f5cb7d23000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-2" #20 daemon prio=5 os_prio=0 cpu=0.09ms elapsed=17.42s tid=0x0000562b11982000 nid=0x25 waiting on condition [0x00007f5cb807b000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-3" #21 daemon prio=5 os_prio=0 cpu=0.35ms elapsed=17.42s tid=0x0000562b10cc7800 nid=0x26 waiting on condition [0x00007f5cb77e5000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-4" #22 daemon prio=5 os_prio=0 cpu=0.10ms elapsed=17.42s tid=0x0000562b13630800 nid=0x27 waiting on condition [0x00007f5cb75ff000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-5" #23 daemon prio=5 os_prio=0 cpu=0.06ms elapsed=17.41s tid=0x0000562b13632000 nid=0x28 waiting on condition [0x00007f5cb74fe000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-6" #24 daemon prio=5 os_prio=0 cpu=0.14ms elapsed=17.41s tid=0x0000562b136f0800 nid=0x29 waiting on condition [0x00007f5cb73fd000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-7" #25 daemon prio=5 os_prio=0 cpu=0.12ms elapsed=17.41s tid=0x0000562b136e0800 nid=0x2a waiting on condition [0x00007f5cb72fc000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-8" #26 daemon prio=5 os_prio=0 cpu=0.09ms elapsed=17.41s tid=0x0000562b136e1800 nid=0x2b waiting on condition [0x00007f5cb71fb000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-9" #27 daemon prio=5 os_prio=0 cpu=0.14ms elapsed=17.41s tid=0x0000562b13621800 nid=0x2c waiting on condition [0x00007f5cb70fa000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-exec-10" #28 daemon prio=5 os_prio=0 cpu=0.14ms elapsed=17.41s tid=0x0000562b1360c000 nid=0x2d waiting on condition [0x00007f5cb6ff9000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@12/Native Method) - parking to wait for <0x00000000fb50ba60> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@12/LockSupport.java:194) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@12/AbstractQueuedSynchronizer.java:2081) at java.util.concurrent.LinkedBlockingQueue.take(java.base@12/LinkedBlockingQueue.java:433) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:107) at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:33) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@12/ThreadPoolExecutor.java:1054) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@12/ThreadPoolExecutor.java:1114) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@12/ThreadPoolExecutor.java:628) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-ClientPoller-0" #29 daemon prio=5 os_prio=0 cpu=2.85ms elapsed=17.40s tid=0x0000562b136cd000 nid=0x2e runnable [0x00007f5cb6ef8000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPoll.wait(java.base@12/Native Method) at sun.nio.ch.EPollSelectorImpl.doSelect(java.base@12/EPollSelectorImpl.java:120) at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@12/SelectorImpl.java:124) - locked <0x00000000fb53c5f8> (a sun.nio.ch.Util$2) - locked <0x00000000fb53c460> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(java.base@12/SelectorImpl.java:136) at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:743) at java.lang.Thread.run(java.base@12/Thread.java:835) "http-nio-8080-Acceptor-0" #30 daemon prio=5 os_prio=0 cpu=0.45ms elapsed=17.40s tid=0x0000562b12115000 nid=0x2f runnable [0x00007f5cb6df7000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.ServerSocketChannelImpl.accept0(java.base@12/Native Method) at sun.nio.ch.ServerSocketChannelImpl.accept(java.base@12/ServerSocketChannelImpl.java:525) at sun.nio.ch.ServerSocketChannelImpl.accept(java.base@12/ServerSocketChannelImpl.java:277) at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:448) at org.apache.tomcat.util.net.NioEndpoint.serverSocketAccept(NioEndpoint.java:70) at org.apache.tomcat.util.net.Acceptor.run(Acceptor.java:95) at java.lang.Thread.run(java.base@12/Thread.java:835) "DestroyJavaVM" #32 prio=5 os_prio=0 cpu=4915.44ms elapsed=17.32s tid=0x0000562b11f9e000 nid=0x6 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Attach Listener" #33 daemon prio=9 os_prio=0 cpu=0.60ms elapsed=15.49s tid=0x0000562b11ff8800 nid=0x3c waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "VM Thread" os_prio=0 cpu=170.49ms elapsed=31.16s tid=0x0000562b0ff90000 nid=0xa runnable "Shenandoah GC Threads#0" os_prio=0 cpu=57.15ms elapsed=31.46s tid=0x0000562b0fe25800 nid=0x7 runnable "Shenandoah GC Threads#1" os_prio=0 cpu=40.46ms elapsed=29.33s tid=0x0000562b111b0000 nid=0x15 runnable "Shenandoah GC Threads#2" os_prio=0 cpu=56.93ms elapsed=29.32s tid=0x0000562b111ae000 nid=0x16 runnable "Shenandoah GC Threads#3" os_prio=0 cpu=47.89ms elapsed=29.30s tid=0x0000562b11562800 nid=0x17 runnable "VM Periodic Task Thread" os_prio=0 cpu=59.59ms elapsed=31.06s tid=0x0000562b1016e000 nid=0x12 waiting on condition JNI global refs: 14, weak refs: 0
使用jcmd pid Thread.print可以打印线程快照
/ # curl -i localhost:8080/actuator/metrics/jvm.threads.daemon HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:49:19 GMT {"name":"jvm.threads.daemon","description":"The current number of live daemon threads","baseUnit":"threads","measurements":[{"statistic":"VALUE","value":20.0}],"availableTags":[]} / # curl -i localhost:8080/actuator/metrics/jvm.threads.peak HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:47:32 GMT {"name":"jvm.threads.peak","description":"The peak live thread count since the Java virtual machine started or peak was reset","baseUnit":"threads","measurements":[{"statistic":"VALUE","value":24.0}],"availableTags":[]} / # curl -i localhost:8080/actuator/metrics/jvm.threads.live HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:47:52 GMT {"name":"jvm.threads.live","description":"The current number of live threads including both daemon and non-daemon threads","baseUnit":"threads","measurements":[{"statistic":"VALUE","value":24.0}],"availableTags":[]} / # curl -i localhost:8080/actuator/metrics/tomcat.threads.current HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:48:31 GMT {"name":"tomcat.threads.current","description":null,"baseUnit":"threads","measurements":[{"statistic":"VALUE","value":10.0}],"availableTags":[{"tag":"name","values":["http-nio-8080"]}]} / # curl -i localhost:8080/actuator/metrics/tomcat.threads.busy HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:48:58 GMT {"name":"tomcat.threads.busy","description":null,"baseUnit":"threads","measurements":[{"statistic":"VALUE","value":1.0}],"availableTags":[{"tag":"name","values":["http-nio-8080"]}]} / # curl -i localhost:8080/actuator/metrics/tomcat.threads.config.max HTTP/1.1 200 Content-Disposition: inline;filename=f.txt Content-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 Transfer-Encoding: chunked Date: Mon, 01 Apr 2019 02:50:15 GMT {"name":"tomcat.threads.config.max","description":null,"baseUnit":"threads","measurements":[{"statistic":"VALUE","value":200.0}],"availableTags":[{"tag":"name","values":["http-nio-8080"]}]}
springboot的actuator默认可以查看jvm.threads开头( jvm.threads.daemon、jvm.threads.peak、jvm.threads.live
)以及tomcat.threads开头( tomcat.threads.current、tomcat.threads.busy、tomcat.threads.config.max
)的metrics;另外使用/actuator/threaddump也可以打印线程快照;不过actuator的metrics没有统计也没有dump出来gc等其他线程,比如C2 CompilerThread0、C1 CompilerThread0、Sweeper thread、Service Thread、VM Thread、Shenandoah GC Threads#0、Shenandoah GC Threads#1、Shenandoah GC Threads#2、Shenandoah GC Threads#3、VM Periodic Task Thread等
查询线程信息
jvm.threads.daemon、jvm.threads.peak、jvm.threads.live
)以及tomcat.threads开头( tomcat.threads.current、tomcat.threads.busy、tomcat.threads.config.max
)的metrics 不过actuator的metrics没有统计也没有dump出来gc等其他线程
)