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