Я запустил jmap, чтобы сделать дамп кучи моего процесса, но jvm выдал ответ:
Невозможно открыть файл сокета: целевой процесс не отвечает или HotSpot VM не загружена
Опция -F может быть использована, когда целевой процесс не отвечает
Пара вопросов:
Использование -F нормально для получения дампа кучи?
Я подождал 20 минут, и процесс не остановился. Есть идеи, почему так?
Ответ 1
jmap vs. jmap -F, а также jstack vs. jstack -F используют совершенно разные механизмы для связи с целевой JVM.
jmap / jstack
При запуске без -F эти инструменты используют механизм динамического присоединения. Это работает следующим образом:
Перед подключением к Java-процессу 1234 jmap создает файл .attach_pid1234 в рабочем каталоге целевого процесса или в /tmp.
Затем jmap посылает SIGQUIT целевому процессу. Когда JVM перехватывает сигнал и находит .attach_pid1234, она запускает поток AttachListener.
Поток AttachListener создает сокет домена UNIX /tmp/.java_pid1234 для прослушивания команд от внешних инструментов.
В целях безопасности, когда принимается соединение (от jmap), JVM проверяет, что учетные данные пира сокета равны euid и egid процесса JVM. Поэтому jmap не будет работать, если его запустит другой пользователь (даже root).
jmap подключается к сокету и посылает команду dumpheap.
Эта команда считывается и выполняется потоком AttachListener JVM. Весь вывод отправляется обратно в сокет. Поскольку дамп кучи делается в процессе непосредственно JVM, операция выполняется очень быстро, однако JVM может делать это только в безопасных соединениях. Если соединение безопасности не может быть достигнуто (например, процесс завис, не отвечает, или идет длительный GC), jmap возьмет таймаут и завершится неудачей.
Давайте подытожим преимущества и недостатки Dynamic Attach.
Плюсы:
Дамп кучи и другие операции выполняются JVM совместно с максимальной скоростью.
Вы можете использовать любую версию jmap или jstack для подключения к любой другой версии JVM.
Минусы:
Инструмент должен быть запущен тем же пользователем (euid/egid), что и целевая JVM.
Может использоваться только на живой и активной JVM.
Не будет работать, если целевая JVM запущена с параметром -XX:+DisableAttachMechanism.
jmap -F / jstack -F
При запуске с параметром -F программа переходит в специальный режим, в котором работает HotSpot Serviceability Agent. В этом режиме целевой процесс замораживается; инструменты читают его память с помощью средств отладки ОС, а именно ptrace в Linux.
jmap -F вызывает PTRACE_ATTACH на целевой JVM. Целевой процесс безоговорочно приостанавливается в ответ на сигнал SIGSTOP.
Программа читает память JVM, используя PTRACE_PEEKDATA. ptrace может читать только одно слово за раз, поэтому для чтения большой кучи целевого процесса требуется слишком много вызовов. Это очень и очень медленно.
Инструмент реконструирует внутренние структуры JVM, основываясь на знании конкретной версии JVM. Поскольку разные версии JVM имеют разную компоновку памяти, режим -F работает, только если jmap из того же JDK, что и целевой Java-процесс.
Инструмент сам создает дамп кучи, а затем возобновляет работу целевого процесса.
Плюсы:
Не требуется никакого коннекта с целевой JVM. Можно использовать даже на зависшем процессе.
ptrace работает всегда, когда достаточно привилегий на уровне ОС. Например, root может делать дамп процессов всех других пользователей.
Минусы:
Очень медленно для больших куч.
Инструмент и целевой процесс должны быть из одной и той же версии JDK.
Безопасное соединение не гарантируется, если инструмент подключается в принудительном режиме. Хотя jmap пытается обработать все особые случаи, иногда может получиться так, что целевая JVM не находится в согласованном состоянии.
Примечание
Существует более быстрый способ получения дампов кучи в принудительном режиме. Сначала создайте дамп кучи с помощью gcore, а затем запустите jmap над сгенерированным файлом кучи.
Ответ 2
Если ваше приложение работает как служба systemd, вам следует открыть файл службы, который находится в каталоге /usr/lib/systemd/system/ и назван именем вашей службы. Затем проверьте, является ли атрибут privateTmp как true.
Если это так, вы должны изменить его на false, а затем обновить сервис командой, как показано ниже:
systemctl daemon-reload
systemctl restart [servicename].
Если вы хотите запустить jmap/jcmd перед перезапуском, вы можете воспользоваться скриптом execStop в файле службы. Просто поместите в него команду и выполните systemctl stop [имя службы].

Linux