Jps Jstat Jstack...的工作原理

本文介绍JDK 8的jps、jstat、jstack … 的工作原理。

Jvmstat Performance Counters

jps和jstat命令使用的是Jvmstat Performance Counters

jps

先说结论:

  • jps命令扫描的是 $TMPDIR/hsperfdata_$usr 下的PID文件。比如在 Linux 系统下,/tmp/hsperfdata_foo/2121,这体现两个信息,JVM进程的PID是2121,启动这个进程的是foo用户。

源码脉络:

所以说,如果你把别的机器的/tmp/hsperfdata_<usr>/<pid> 复制到你本地,jps也是能够返回结果的。

但是,前提是PID得在你的机器上存在,比如别的机器上PID是2121,那么你的机器上也必须有PID=2121的进程,无论这个进程是什么。否则jps会返回 -- process information unavailable 这样的信息。

如果你这样执行jps(其实所有命令都可以这样执行),可以看到异常:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
java -cp $JAVA_HOME/lib/tools.jar -Djps.debug=true -Djps.printStackTrace=true sun.tools.jps.Jps

sun.jvmstat.monitor.MonitorException: 2121 not found
        at sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:84)
        at sun.jvmstat.perfdata.monitor.protocol.local.LocalMonitoredVm.<init>(LocalMonitoredVm.java:68)
        at sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.getMonitoredVm(MonitoredHostProvider.java:77)
        at sun.tools.jps.Jps.main(Jps.java:92)
Caused by: java.lang.IllegalArgumentException: Process not found
        at sun.misc.Perf.attach(Native Method)
        at sun.misc.Perf.attachImpl(Perf.java:270)
        at sun.misc.Perf.attach(Perf.java:200)
        at sun.jvmstat.perfdata.monitor.protocol.local.PerfDataBuffer.<init>(PerfDataBuffer.java:64)
        ... 3 more

顺着这个错误分析PerfDataBuffer.java,可以发现解决的办法就是创建一个/tmp/hsperfdata_<pid>的文件。

jstat

先说结论:

  • jstat和jps一样,读取的是 $TMPDIR/hsperfdata_$usr 下的PID文件,这个文件准确来说应该是 perfdata。这里面有 jstat 所想要的一切。
  • JVM在运行过程中会更新 perfdata,perfdata 采用的是mmap机制(内存映射文件),详见JVM源码分析之jstat工具原理完全解读
  • 顺带一提,mmap文件内容的修改是无法通过 inotify(7) 探测到的(见Limitations and caveats)。

源码脉络:

Dynamic Attach Mechanism

jstack和jmap命令使用的是Dynamic Attach Mechanism

jstack

先说结论:

  • 和socket文件 /tmp/.java_pid$pid 通信
  • 如果这个文件不存在,则 touch /proc/$pid/cwd/.attach_pid$pid文件
  • 然后 kill -3 $pid,JVM就会创建socket文件
  • 然后把attach_pid$pid文件可以删掉

源码脉络:

jmap

jmap的机制和jstack一摸一样,不做赘述。

参考资料

版权

评论