bigywater.tech
Java · 204

Attach API:如何连接一个正在运行的 JVM

jcmd、jstack、各种 APM 都是通过 Attach API 连进正在运行的 JVM 的。这篇自己写 attach 的客户端,把握手、读取属性、动态加载 agent 与失败情形逐项做一遍(Instrumentation 与 HotSwap 见前面的篇目)。

113 ms
attach 到另一个 JVM 的用时
Attach Listener
动态加载的 agent 的 agentmain 所在线程
Can not attach to current VM
默认不允许 attach 到自己

attach、读取属性与动态加载 agent

实测 · 本机执行输出
  VirtualMachine.list() 看到的 JVM 数 = 5,其中包含目标 pid 63781:true;目标的 displayName = Target
  attach 之前 .java_pid63781 存在吗:false
  attach(63781) 成功,用时 113 ms;之后 .java_pid63781 存在吗:true(目标进程创建的 UNIX 套接字文件)
  getSystemProperties():java.version = 21.0.12.1,user.dir 以 …/py40 结尾,共 52 项
  getAgentProperties() 里有 3 项,例如 sun.jvm.args = ,sun.java.command = Target
  loadAgent(agent2.jar, "hello-args") 返回,用时 17 ms(agentmain 在目标进程里执行,输出出现在目标的 stdout)
  detach 之后 .java_pid63781 还存在吗:true
  目标进程自己的输出(agent 在目标进程里运行时打印的):
    WARNING: A Java agent has been loaded dynamically (<jtmp>/j64/agent2.jar)
    WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
    WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
    WARNING: Dynamic loading of agents will be disallowed by default in a future release
      [target] agentmain 被调用,参数 = hello-args,线程 = Attach Listener,已加载类数 = 1097
      [target] 看到 mode 被改成了 changed-by-agent

失败情形

实测 · 本机执行输出
  attach 到 pid 1(不是 JVM):AttachNotSupportedException: pid: 1, state is not ready to participate in attach handshake!
  attach 到不存在的 pid:AttachNotSupportedException: pid: 99999999, state is not ready to participate in attach handshake!
  attach 到自己的进程:IOException: Can not attach to current VM
  loadAgent 一个不存在的 jar:AgentLoadException: Agent JAR not found or no Agent-Class attribute

分步演示

Attach API
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,macOS(.java_pid 套接字在临时目录里,Linux 的位置和握手方式(/proc、信号)不同,本篇没有验证)
    • 没有验证:Linux 上的 attach 握手、不同用户之间的 attach 权限、容器里 pid 命名空间的影响、-XX:+DisableAttachMechanism 的效果、jcmd/jstack 的实现细节、startLocalManagementAgent;detach 后套接字文件仍在的原因没有查
    京ICP备2026067502号-1京公网安备11010502063487号