Talk about jvm Stack Memory

  jvm

Order

This article mainly studies the jvm Stack Memory.

Virtual Machine Stack

  • Each jvm thread has a private Virtual Machine Stack, which is created at the same time as the thread
  • This stack is mainly used to store frames, which is called stack frames.
  • Each method creates a stack frame when executing, which is used to store local variables, return values, operatedstack, etc. of the method.

Stack Memory

  • Stack Memory is the memory used when executing threads. They include some short-life values used by methods and references to objects in heap.
  • Stack Memory is referenced in the order of LIFO (Last-In-First-Out). Every time a method is called, an area is created in stack memory to store the original type of value and the reference of objects in heap. When the execution of the method ends, this area is released and can be used by the next method. Stack memory is a very small piece compared to heap memory. The size of stack memory can be specified by -Xss or -XX:ThreadStackSize.
  • When the stack size required by a thread exceeds the set size, the jvm will throw StackOverflowError; ; When the system does not have enough memory for the jvm to create a new thread, the jvm will throw OutOfMemoryError

StackOverflowError instance

    /**
     * -Xss144k
     */
    @Test
    public void testStackOverflow(){
        recursiveInvoke();
    }

    public void recursiveInvoke(){
        String uuid = UUID.randomUUID().toString();
        recursiveInvoke();
    }

The abnormal output is as follows:

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)

The larger the Xss, the larger the size of each thread, the more memory it occupies, and the fewer threads it can create. The smaller Xss is, the smaller the recursion depth is, and the stack overflow java.lang.StackOverflowError is easy to occur. Reducing the declaration of local variables can save stack frame size and increase call depth.

OOMKilled instance

  • Code instance
    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 command started
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
  • docker 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",
    //......
]

You can see that OOMKilled in State is true.

OutOfMemoryError instance

  • Code instance
    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);
        }
    }
  • Operating parameters
-server
-Xmx128m
-Xss1m
-XX:ParallelGCThreads=4
-XX:ConcGCThreads=4
-XX:+UnlockDiagnosticVMOptions
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp
-Djava.io.tmpdir=/tmp

If you do not use docker and execute it directly on this machine, you can see the following error report

  • Abnormal output
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]

View thread information

View thread stack size

/ # 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)

Use JCMD PID VM. NATIVE _ MEMORY SCALE = MB to view the information of the thread stack. Specifically, in the Thread section, there are 36 threads, and the reserved size of the stack is 36 m.

View thread snapshots

/ # 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

Print allows you to print thread snapshots.

View spring boot running thread information

/ # 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’s actuator can view the beginning of jvm.threads (jvm.threads.daemon、jvm.threads.peak、jvm.threads.live) and the beginning of tomcat.threads (tomcat.threads.current、tomcat.threads.busy、tomcat.threads.config.maxMetrics; for In addition, thread snapshots can also be printed using/actor/threaddump; However, actuator’s metrics does not have statistics or dump other threads such as gc. For example, c2compilerthreads 0, c1compilerthreads 0, Sweeper thread, Service Thread, vmthreads, Shenandoah GC Threads#0, Shenandoah GC Threads#1, Shenandoah GC Threads#2, Shenandoah GC Threads#3, vmperiodictaskthreads, etc.

Summary

  • Each jvm thread has a private Virtual Machine Stack, which is created at the same time as the thread; This stack is mainly used to store frames, which is called stackframes. Each method creates a stack frame when executing, which is used to store local variables, return values, operatedstack, etc. of the method.
  • Stack Memory is the memory used when executing threads. They include some short-life values used by methods and references to objects in heap. Stack M emory is referenced in the order of LIFO (Last-In-First-Out). Every time a method is called, an area is created in stack memory to store the original type of value and the reference of objects in heap. When the execution of the method ends, this area is released and can be used by the next method. Stack memory is a very small piece compared to heap memory. The size of stack memory can be specified through -Xss or -XX:ThreadStackSize; When the stack size required by a thread exceeds the set size, the jvm will throw StackOverflowError; ; When the system does not have enough memory for the jvm to create a new thread, the jvm will throw OutOfMemoryError
  • Query thread information

    • Use jcmdpidvm.native _ memoryscale = mb to view the thread stack information, specifically in the threadsection.
    • Print allows you to print thread snapshots.
    • Springboot’s actuator can view the beginning of jvm.threads (jvm.threads.daemon、jvm.threads.peak、jvm.threads.live) and the beginning of tomcat.threads (tomcat.threads.current、tomcat.threads.busy、tomcat.threads.config.max) of the internet.
    • You can also print thread snapshots (However, actuator's metrics does not have statistics or dump other threads such as gc.)

doc