序本文主要研究一下jvm的Stack MemoryVirtual Machine Stack每个jvm线程都有一个私有的Virtual Machine Stack,它在线程同时被创建该stack主要用于存储frames,即所谓的stack frames每个方法在执行的时候都会创建一个stack frame,用于存储方法的局部变量、返回值、Operand stack等Stack MemoryStack Memory是执行线程时所使用的内存,他们包含了方法用到的一些短生命周期的values及heap中objects的引用Stack Memory是按照LIFO (Last-In-First-Out)的顺序被引用的,每当一个方法被调用,都会在stack memory中创建一块区域用于保存原始类型的值及heap中objects的引用;当方法执行结束时,这块区域就被释放可以被下一个方法使用;相对于heap memory来说,stack memory是非常小的一块。通过-Xss或者-XX:ThreadStackSize可以指定stack memory的大小当一个线程所需的stack size超过了设定的大小是,jvm会抛出StackOverflowError;而当系统没有足够内存可以供jvm创建一个新线程时,jvm会抛出OutOfMemoryErrorStackOverflowError实例 /** * -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。减少局部变量的声明,可以节省栈帧大小,增加调用深度。OOMKilled实例代码实例 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命令启动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’ \demodocker inspect containerId[ { “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为trueOutOfMemoryError实例代码实例 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]查看thread信息查看thread stack size/ # jcmd 1 VM.native_memory scale=MB1: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.print1:2019-04-01 10:43:13Full 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 conditionJNI global refs: 14, weak refs: 0使用jcmd pid Thread.print可以打印线程快照查看spring boot运行线程信息/ # curl -i localhost:8080/actuator/metrics/jvm.threads.daemonHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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.peakHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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.liveHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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.currentHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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.busyHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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.maxHTTP/1.1 200Content-Disposition: inline;filename=f.txtContent-Type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8Transfer-Encoding: chunkedDate: 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线程都有一个私有的Virtual Machine Stack,它在线程同时被创建;该stack主要用于存储frames,即所谓的stack frames;每个方法在执行的时候都会创建一个stack frame,用于存储方法的局部变量、返回值、Operand stack等Stack Memory是执行线程时所使用的内存,他们包含了方法用到的一些短生命周期的values及heap中objects的引用;Stack Memory是按照LIFO (Last-In-First-Out)的顺序被引用的,每当一个方法被调用,都会在stack memory中创建一块区域用于保存原始类型的值及heap中objects的引用;当方法执行结束时,这块区域就被释放可以被下一个方法使用;相对于heap memory来说,stack memory是非常小的一块。通过-Xss或者-XX:ThreadStackSize可以指定stack memory的大小;当一个线程所需的stack size超过了设定的大小是,jvm会抛出StackOverflowError;而当系统没有足够内存可以供jvm创建一个新线程时,jvm会抛出OutOfMemoryError查询线程信息使用jcmd pid VM.native_memory scale=MB可以查看thread stack的信息,具体在Thread部分使用jcmd pid Thread.print可以打印线程快照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等其他线程)docJava线程与Xss2.5.2. Java Virtual Machine StacksJVMInternalsJVM memory modelJava Heap Space vs Stack – Memory Allocation in JavaHow does Java (JVM) allocate stack for each threadJVM Stacks and Stack FramesA Visual Look at JVM Stacks and FramesStack Memory and Heap Space in JavaJava: What is the limit to the number of threads you can create?Troubleshoot OutOfMemoryError: Unable to Create New Native ThreadJDK 8: Thread Stack Size TuningJVM Tuning: Heapsize, Stacksize and Garbage Collection Fundamental