Java 使用 jcmd 命令查看虚拟线程堆栈信息

Java juc jcmd About 6,348 words

Thread.dump_to_file

jcmd中的Thread相关命令有Thread.printThread.dump_to_file(还有Thread.vthread相关命令)。

Thread.print中不能查看虚拟线程相关命令,需使用Thread.dump_to_file将线程信息导出到文件后查看。

PS \openjdk-25> jcmd 20308 help Thread.dump_to_file
20308:
Thread.dump_to_file
Dump threads, with stack traces, to a file in plain text or JSON format.

Impact: Medium: Depends on the number of threads.

Syntax : Thread.dump_to_file [options] <filepath>

Arguments:
        filepath :  The file path to the output file (FILE, no default value)

Options: (options must be specified using the <key> or <key>=<value> syntax)
        -overwrite : [optional] May overwrite existing file (BOOLEAN, false)
        -format : [optional] Output format ("plain" or "json") (STRING, plain)

format

Thread.dump_to_file可以使用-format参数指定导出后文件的格式。

overwrite

是否覆盖已存在的文件。

使用

jcmd <pid> Thread.dump_to_file -format=json ~/thread.json

堆栈信息

虚拟线程会有virtual: true的标识。

{
  "threadDump": {
    "processId": "14244",
    "time": "2025-10-10T07:39:23.174417600Z",
    "runtimeVersion": "25+36-3489",
    "threadContainers": [
      {
        "container": "<root>",
        "parent": null,
        "owner": null,
        "threads": [
          {
            "tid": "3",
            "time": "2025-10-10T07:39:23.187416900Z",
            "name": "main",
            "state": "TIMED_WAITING",
            "parkBlocker": {
              "object": "java.util.concurrent.CountDownLatch$Sync@3df72b07"
            },
            "stack": [
              "java.base\/jdk.internal.misc.Unsafe.park(Native Method)",
              "java.base\/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:271)",
              "java.base\/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:792)",
              "java.base\/java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1166)",
              "java.base\/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:276)",
              "java.base\/java.util.concurrent.ThreadPerTaskExecutor.awaitTermination(ThreadPerTaskExecutor.java:159)",
              "java.base\/java.util.concurrent.ThreadPerTaskExecutor.awaitTermination(ThreadPerTaskExecutor.java:173)",
              "java.base\/java.util.concurrent.ThreadPerTaskExecutor.close(ThreadPerTaskExecutor.java:189)",
              "com.center.FJPMain.main(FJPMain.java:18)"
            ]
          },
          {
            "tid": "25",
            "time": "2025-10-10T07:39:23.198423300Z",
            "name": "VirtualThread-unblocker",
            "state": "RUNNABLE",
            "stack": [
              "java.base\/java.lang.VirtualThread.takeVirtualThreadListToUnblock(Native Method)",
              "java.base\/java.lang.VirtualThread.unblockVirtualThreads(VirtualThread.java:1507)",
              "java.base\/java.lang.Thread.run(Thread.java:1474)",
              "java.base\/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:148)"
            ]
          },
          {
            "tid": "80",
            "time": "2025-10-10T07:39:23.199417200Z",
            "name": "Read-Poller",
            "state": "RUNNABLE",
            "stack": [
              "java.base\/sun.nio.ch.WEPoll.wait(Native Method)",
              "java.base\/sun.nio.ch.WEPollPoller.poll(WEPollPoller.java:61)",
              "java.base\/sun.nio.ch.Poller.pollerLoop(Poller.java:248)",
              "java.base\/java.lang.Thread.run(Thread.java:1474)",
              "java.base\/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:148)"
            ]
          },
          {
            "tid": "81",
            "time": "2025-10-10T07:39:23.199417200Z",
            "name": "Write-Poller",
            "state": "RUNNABLE",
            "stack": [
              "java.base\/sun.nio.ch.WEPoll.wait(Native Method)",
              "java.base\/sun.nio.ch.WEPollPoller.poll(WEPollPoller.java:61)",
              "java.base\/sun.nio.ch.Poller.pollerLoop(Poller.java:248)",
              "java.base\/java.lang.Thread.run(Thread.java:1474)",
              "java.base\/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:148)"
            ]
          },
          ...
        ],
        "threadCount": "11"
      },
      {
        "container": "ForkJoinPool.commonPool\/jdk.internal.vm.SharedThreadContainer@625d8625",
        "parent": "<root>",
        "owner": null,
        "threads": [
        ],
        "threadCount": "0"
      },
      {
        "container": "java.util.concurrent.ThreadPoolExecutor@2c42d3fb",
        "parent": "<root>",
        "owner": null,
        "threads": [
        ],
        "threadCount": "0"
      },
      {
        "container": "ForkJoinPool-1\/jdk.internal.vm.SharedThreadContainer@5c8e12cf",
        "parent": "<root>",
        "owner": null,
        "threads": [
        ],
        "threadCount": "0"
      },
      {
        "container": "java.util.concurrent.ThreadPerTaskExecutor@3bb940ce",
        "parent": "<root>",
        "owner": null,
        "threads": [
          {
            "tid": "26",
            "time": "2025-10-10T07:39:23.207418700Z",
            "virtual": true,
            "name": "",
            "state": "WAITING",
            "stack": [
              "java.base\/java.lang.VirtualThread.park(VirtualThread.java:738)",
              "java.base\/java.lang.System$1.parkVirtualThread(System.java:2284)",
              "java.base\/java.util.concurrent.locks.LockSupport.park(LockSupport.java:367)",
              "com.center.FJPMain.lambda$main$0(FJPMain.java:15)",
              "java.base\/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)",
              "java.base\/java.util.concurrent.FutureTask.run(FutureTask.java:328)",
              "java.base\/java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture.run(ThreadPerTaskExecutor.java:323)",
              "java.base\/java.lang.VirtualThread.run(VirtualThread.java:456)"
            ]
          }
        ],
        "threadCount": "1"
      }
    ]
  }
}

测试代码

public class TestMain {
    public static void main(String[] args) throws Throwable {
        try (ExecutorService executorService = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory())) {
            executorService.submit(() -> {
                LockSupport.park();
            });
        }
    }
}
Views: 14 · Posted: 2025-12-27

———         Thanks for Reading         ———

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓
Prev Post
Today In History
Browsing Refresh