构建我自己的分析器,我使用JVMTI API 来构建本机库代理。通过使用附加参数 -agentlib 可以与 JVM 一起启动此代理。此外还有Attach API,它允许将代理注入到正在运行的 JVM 中。我想使用以下代码在我的分析器中实现此功能:
try {
String pid = VirtualMachine.list().get(0).id();
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgentLibrary("agent");
} catch (AgentLoadException e1) {
e1.printStackTrace();
} catch (AgentInitializationException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (AttachNotSupportedException e) {
e.printStackTrace();
}
它有什么作用?从所有可用的正在运行的虚拟机 ( VirtualMachine.list()
) 中,我选择第一个,附加到它并尝试将我的代理加载到其中。可以找到名为 libagent.so 的 UNIX 系统上的代理,但在尝试加载代理时会引发以下异常:
com.sun.tools.attach.AttachNotSupportedException:
Unable to open socket file:
target process not responding or HotSpot VM not loaded.
查看源代码,抛出此异常,因为它找不到名为.java_pid<pid>
. 我在文档中没有找到很多关于这种文件的信息。我经常听说这种文件不再使用了,但我正在运行 Java 1.6。
我还尝试附加到其他 JVM,实际上我保持这个附加过程是动态的,出于测试原因,我只是尝试附加到任何 JVM。
这是导致异常的代码,取自sun.tools.attach: LinuxVirtualMachine.java:
// Return the socket file for the given process.
// Checks working directory of process for .java_pid<pid>. If not
// found it looks in /tmp.
private String findSocketFile(int pid) {
// First check for a .java_pid<pid> file in the working directory
// of the target process
String fn = ".java_pid" + pid;
String path = "/proc/" + pid + "/cwd/" + fn;
File f = new File(path);
if (!f.exists()) {
// Not found, so try /tmp
path = "/tmp/" + fn;
f = new File(path);
if (!f.exists()) {
return null; // not found
}
}
return path;
}
它说,它正在从根/proc/<pid>
目录中查找。查看 JDK7 的变更集,他们似乎正在将代码JDK7 变更集更改为 LinuxVirtualMachine