Создавая собственный профилировщик, я использую API JVMTI для создания собственного агента библиотеки. Этот агент может быть запущен вместе с JVM с помощью дополнительного параметра -agentlib. Кроме того, существует API Attach , который позволяет внедрить агент в работающую 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()
) я выбираю первую, подключаюсь к ней и пытаюсь загрузить в нее свой агент. Агент в системах UNIX с именем libagent.so можно найти, но при попытке загрузить агент выдается следующее исключение:
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;
}
Там написано, что он ищет root в каталоге /proc/<pid>
. Глядя на набор изменений JDK7, кажется, что они вносят изменения в код Набор изменений JDK7 для LinuxVirtualMachine