AttachNotSupportedException из-за отсутствия файла java_pid в Attach API - PullRequest
12 голосов
/ 24 апреля 2011

Создавая собственный профилировщик, я использую 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

Ответы [ 2 ]

28 голосов
/ 20 декабря 2012

Я испытал эту же проблему.

Исключение в потоке "main" com.sun.tools.attach.AttachNotSupportedException: невозможно открыть файл сокета: целевой процесс не отвечает или виртуальная машина HotSpot не загружена

Было найдено решение, если поискать немного.

Первый ответ пришел http://www.jvmmonitor.org/doc/index.html. Появляется ошибка:

Если вы видите дополнительное сообщение «Невозможно открыть файл сокета: цель процесс не отвечает или Hotspot VM не загружен ", либо ваш приложение не отвечает, создавая файл сокета, как /tmp/.java_pid1234 (например, из-за зависания, разрешения файловой системы) или Монитор JVM не смог найти созданный файл сокета (например, из-за ошибка 7009828).

Затем, после еще нескольких поисков, я обнаружил на github разговор о другом инструменте, у которого был такой же симптом: «Невозможно открыть файл сокета» (https://github.com/rhuss/jolokia/issues/34):

jgreen: вызвано: com.sun.tools.attach.AttachNotSupportedException: Невозможно открыть файл сокета: целевой процесс не отвечает или виртуальная машина HotSpot не загружена

jgreen: правильно, у меня это работает, но только при запуске как тот же пользователь, что и activemq. рут не работает

Этот последний кусок был решением. Единственный способ, которым этот вызов .attach был бы успешным, состоял в том, чтобы выполнить код java, который вызывает присоединение от имени пользователя , который был тем, кто владел процессом, выполняющим jvm. В моем случае это был пользователь activemq.

System.out.println("HEAP: " + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());

HEAP: init = 27127296(26491K) used = 3974200(3881K) committed = 26345472(25728K) max = 675086336(659264K)
3 голосов
/ 29 апреля 2011

I подозреваю , что вы, возможно, указываете -Djava.io.tmpdir для используемой JVM и на Java 6 с обновлением 23 или 24. Если это так, вам просто нужно обновить его до Update25 для работающего экземпляра.

Единственная ссылка на эту проблему, которую я видел, это Jstack и Jstat перестали работать с обновлением до JDK6u23 .Я определенно видел ту же проблему с обновлением 23 и сбоем jstack, где он работал нормально до 23 и снова работает с 25. Я также только что попробовал VirtualMachine.attach(pid) против 23, и он не работает, если используется -Djava.io.tmpdir.Работает с 25.

...