Запуск jmap и невозможность открытия файла сокета

88

Мне пришлось запустить jmap, чтобы снять дамп моего процесса. но jvmвернулся:

Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

Итак, я использовал -F:

./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...
  1. Использование -F является Allright для принятия дамп кучи?
  2. Жду 20 минут и еще не закончил. Есть идеи, почему?
Rayman
источник

Ответы:

187

jmapvs. jmap -F, а также jstackvs. jstack -Fиспользуют совершенно разные механизмы для взаимодействия с целевой JVM.

jmap / jstack

При запуске без -Fэтих инструментов используйте механизм динамического присоединения . Это работает следующим образом.

  1. Перед подключением к процессу 1234 Java jmapсоздает файл .attach_pid1234в рабочем каталоге целевого процесса или в /tmp.

  2. Затем jmapотправляет SIGQUITв целевой процесс. Когда JVM улавливает сигнал и находит .attach_pid1234его, она запускает AttachListenerпоток.

  3. AttachListenerthread создает сокет домена UNIX /tmp/.java_pid1234для прослушивания команд от внешних инструментов.

  4. По соображениям безопасности, когда соединение (от jmap) принимается, JVM проверяет, что учетные данные однорангового узла сокета равны euidи egidпроцесса JVM. Поэтому jmapне будет работать, если запущен другим пользователем (даже root).

  5. jmapподключается к сокету и отправляет dumpheapкоманду.

  6. Эта команда читается и выполняется AttachListenerпотоком JVM. Весь вывод отправляется обратно в сокет. Поскольку дамп кучи выполняется непосредственно JVM в процессе, операция выполняется очень быстро. Однако JVM может делать это только в точках безопасности . Если точка безопасности не может быть достигнута (например, процесс завис, не отвечает или выполняется длинный сборщик мусора), jmapпроизойдет тайм-аут и произойдет сбой.

Подведем итоги преимуществ и недостатков Dynamic Attach.

Плюсы.

  • Дамп кучи и другие операции выполняются совместно JVM на максимальной скорости.
  • Вы можете использовать любую версию jmapили jstackподключаться к любой другой версии JVM.

Минусы.

  • Инструмент должен запускаться тем же пользователем ( euid/ egid), что и целевая JVM.
  • Может использоваться только на работающей и работающей JVM.
  • Не будет работать, если целевая JVM запущена с -XX:+DisableAttachMechanism.

jmap -F / jstack -F

При запуске с -Fинструментами переключитесь в специальный режим, в котором есть HotSpot Serviceability Agent . В этом режиме целевой процесс заморожен; инструменты читают его память через средства отладки ОС, а именно ptraceв Linux.

  1. jmap -Fвызывает PTRACE_ATTACHцелевую JVM. Целевой процесс безоговорочно приостанавливается в ответ на SIGSTOPсигнал.

  2. Инструмент читает память JVM, используя PTRACE_PEEKDATA. ptraceможет читать только одно слово за раз, поэтому для чтения большой кучи целевого процесса требуется слишком много вызовов. Это очень и очень медленно.

  3. Инструмент восстанавливает внутренние структуры JVM на основе информации о конкретной версии JVM. Поскольку разные версии JVM имеют разную структуру памяти, -Fрежим работает только в том случае, если он jmapисходит из того же JDK, что и целевой процесс Java.

  4. Инструмент сам создает дамп кучи, а затем возобновляет целевой процесс.

Плюсы.

  • Никакого взаимодействия с целевой JVM не требуется. Может использоваться даже в зависшем процессе.
  • ptraceработает, когда достаточно прав на уровне ОС. Например, rootможет сбрасывать процессы всех остальных пользователей.

Минусы.

  • Очень медленно для больших куч.
  • Инструмент и целевой процесс должны быть из одной версии JDK.
  • Точка сохранения не гарантируется, когда инструмент подключается в принудительном режиме. Хотя он jmapпытается обрабатывать все особые случаи, иногда может случиться так, что целевая JVM не находится в согласованном состоянии.

Запись

Есть более быстрый способ получить дампы кучи в принудительном режиме. Сначала создайте coredump с gcore, а затем запустите jmapсгенерированный файл ядра. См. Соответствующий вопрос .

апангин
источник
85

Я только что обнаружил, что jmap (и, предположительно, jvisualvm при использовании его для создания дампа кучи) предписывает, чтобы пользователь, запускающий jmap, был тем же пользователем, который запускает процесс, пытающийся сбросить.

в моем случае jvm, для которого мне нужен дамп кучи, запускается пользователем linux «jboss». Итак, где sudo jmap -dump:file.bin <pid>сообщалось «Невозможно открыть сокет:», я смог получить дамп кучи, используя:

sudo -u jboss jmap -dump:file.bin <pid>
ben_wing
источник
Я думаю, это должен быть \ -dump: file.bin <pid>, поскольку вам нужно избежать - при передаче параметра из sudo в jmap.
Адам
Это оно! Вам также нужно использовать sudo для jmap и jcmd.
xtian
вау .. Это действительно сработало. Это должен быть принятый ответ
Лалит Рао
3

Как сказал ben_wing , вы можете работать с:

sudo -u jboss-as jmap -dump:file.bin <pid>

(в моем случае это пользователь jboss-as, но может быть ваш jbossили другой.)

Но этого было недостаточно, потому что он запрашивал у меня пароль ( [sudo] password for ec2-user:), хотя я мог работать sudoбез запроса пароля с другими командами.

Я нашел решение здесь , и мне просто нужно было sudoсначала добавить еще одно :

sudo sudo -u jboss-as jmap -dump:file.bin <pid>

Он работает с другими командами, такими как jcmdи jinfo.

Лукас Баскеротто
источник
Дважды sudoспасает мне день!
Sher10ck
[root@v5 ~]# sudo sudo -u es jmap -dump:file=tmp.bin 26283 получается ошибка sudo: jmap: command not found. Я уже настроил путь java в .bash_profile, что мне делать.
roamer
@roamer Может быть, это потому, что, когда вы запускаете как esпользователь, .bash_profileне применяется (потому что профиль bash связан с вашим пользователем, я полагаю). Я советую включить путь java более глобальным способом или, возможно, указать путь java в команде, например sudo sudo -u es PATH="$PATH:/java/path" jmap -dump:file=tmp.bin 26283(где /java/pathнаходится путь java, и убедитесь, что он есть jmapв нем ).
Лукас Баскеротто
Я настраиваю путь java в /home/es/.bash_profile, и я могу использовать jmap при входе в систему с пользователем es. Этот cmd sudo sudo -u es /usr/java/jdk1.8.0_181-cloudera/bin/jmap -dump:file=tmp.bin 26283работает. Большое спасибо.
roamer
2

Если ваше приложение работает как служба systemd, вы должны открыть служебный файл, который находится под /usr/lib/systemd/system/именем вашей службы и назван по нему. Затем проверьте, есть ли privateTmp атрибут .

Если это правда, вы должны изменить его на false, а затем обновить службу с помощью следующей команды: systemctl daemon-reload systemctl restart [servicename] Если вы хотите запустить jmap / jcmd перед перезапуском, вы можете использовать сценарий execStop в служебном файле. Просто введите в него команду и выполнитеsystemctl stop [service name]

просто
источник
Прежде чем я обновил /usr/lib/systemd/system/elasticsearch.service, установив для privateTmp значение false, я получил эту ошибку: Невозможно открыть файл сокета: целевой процесс не отвечает или виртуальная машина HotSpot не загружена - хотя я запускал jmap как пользователь elasticsearch
imdibiji