JVM 的 "VM Thread" 线程

最近在帮一个同事看一个 Java 应用为什么会被经常重启的时候, 定位到 Java 应用中一个线程经常以 CPU 使用率100%的方式出现在 htop 的头部, 它是什么线程, 为什么会导致一个 CPU 100%? 这引起了我的兴趣.

相关背景及症状表现

这个应用程序运行中一个有8个 CPU 的 VM 上面, 经常看到该应用程序已最低13%的使用率运行, 有时候CPU 使用率会突然升到100%, 不过大多数会以13%或稍高来运行. 从 htop 的结果可以看到, 主要一个是一个线程导致一个 CPU 100% 运行:
cpu1.png

上面的截图中 25179 是 Java 进程ID, 25201 是占用一个 CPU core 的 Java 线程. 从 Thread dump 或者 Linux 的 proc 文件系统可以看到该线程的名字:

appUser@appHost:$ cat /proc/25179/task/25201/status
Name:    VM Thread
State:    R (running)
Tgid:    25179
Ngid:    0
Pid:    25201
PPid:    1626
TracerPid:    0

从上面的 shell 输出中可以看到, 该线程名字是 "VM Thread", 它经常单独占用一个 CPU core, 并且导致它100%.

VM Thread 做什么的?

"VM Thread" 是 JVM 自身启动的一个线程, 它主要用来协调其它线程达到安全点(Safepoint). 需要达到安全点的线程主要有: Stop the world 的 GC, 做 thread dump, 线程挂起以及偏向锁的撤销.
一般在 Thread dump 中, 它的表现为下面的样子, 没有线程栈信息:

"VM Thread" os_prio=0 tid=0x00007f5a212dc000 nid=0x1ad8d runnable

同时, 在 Thread dump 中, 有很多线程虽然当时不需要锁同步, 却能看到很多线程在 BLOCKED 状态, 如下:


"MyThreadPool-2" #77 daemon prio=5 os_prio=0 tid=0x00007f597a01c000 nid=0x1ae5e waiting for monitor entry [0x00007f591558a000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at com.sun.org.apache.xml.internal.dtm.ref.DTMManagerDefault.<init>(DTMManagerDefault.java:96)
    at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.<init>(XSLTCDTMManager.java:68)
    at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.newInstance(XSLTCDTMManager.java:78)

为什么这里出现 VM Thread 占用这么多 CPU

原因是这个程序因为内存泄漏, heap 几乎用光, 使用 jstat 命令看到, 每隔大约3s左右, 就有一次新的 full GC, 而CMS 的 full GC 只有单线程在工作, 所以只有一个 CPU core 在忙.

Refer:

  1. https://blog.jamesdbloom.com/JVMInternals.html
  2. http://hg.openjdk.java.net/jdk9/jdk9/hotspot/file/385668275400/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp

标签: none

添加新评论