JVM 的 "VM Thread" 线程
最近在帮一个同事看一个 Java 应用为什么会被经常重启的时候, 定位到 Java 应用中一个线程经常以 CPU 使用率100%的方式出现在 htop 的头部, 它是什么线程, 为什么会导致一个 CPU 100%? 这引起了我的兴趣.
相关背景及症状表现
这个应用程序运行中一个有8个 CPU 的 VM 上面, 经常看到该应用程序已最低13%的使用率运行, 有时候CPU 使用率会突然升到100%, 不过大多数会以13%或稍高来运行. 从 htop 的结果可以看到, 主要一个是一个线程导致一个 CPU 100% 运行:
上面的截图中 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: