Подтвердить что ты не робот

Jmap не может подключиться для создания дампа

У нас есть открытая бета-версия приложения, которое иногда приводит к переполнению кучи. JVM реагирует на постоянный отпуск.

Чтобы проанализировать это, я хотел бы заглянуть в память в тот момент, когда она не удалась. Java не хочет, чтобы я это делал. Процесс все еще находится в памяти, но он, похоже, не распознается как процесс Java.

Сервер, о котором идет речь, является сервером debian Lenny, Java 6u14

/opt/jdk/bin# ./jmap -F -dump:format=b,file=/tmp/apidump.hprof 11175
Attaching to process ID 11175, please wait...
sun.jvm.hotspot.debugger.NoSuchSymbolException: Could not find symbol "gHotSpotVMTypeEntryTypeNameOffset" in any of the known library names (libjvm.so, libjvm_g.so, gamma_g)
at sun.jvm.hotspot.HotSpotTypeDataBase.lookupInProcess(HotSpotTypeDataBase.java:390)
at sun.jvm.hotspot.HotSpotTypeDataBase.getLongValueFromProcess(HotSpotTypeDataBase.java:371)
at sun.jvm.hotspot.HotSpotTypeDataBase.readVMTypes(HotSpotTypeDataBase.java:102)
at sun.jvm.hotspot.HotSpotTypeDataBase.<init>(HotSpotTypeDataBase.java:85)
at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:568)
at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494)
at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:332)
at sun.jvm.hotspot.tools.Tool.start(Tool.java:163)
at sun.jvm.hotspot.tools.HeapDumper.main(HeapDumper.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.tools.jmap.JMap.runTool(JMap.java:179)
at sun.tools.jmap.JMap.main(JMap.java:110)
Debugger attached successfully.
sun.jvm.hotspot.tools.HeapDumper requires a java VM process/core!
4b9b3361

Ответ 1

Решение было очень простым. Я запускал jmap как root, но мне приходилось запускать его как пользователя, который начал jvm. Теперь я скрою голову от стыда.

Ответ 2

Я запускал jmap и приложение с тем же пользователем и все еще получаю ошибку.

Решение было выполнено с точностью до jmap

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

Чем просто использовать jmap и будет отлично работать

jmap -heap 17210

Ответ 3

Будущие гуглеры:

Это также может произойти, если вы установили JDK, пока процесс jmap был запущен.

Если это произойдет, перезапустите java-процесс.

Ответ 4

Если кто-то пытается получить кучу кучи Java-приложения в контейнере Docker. Это единственное решение, которое сработало для меня:

docker exec <container-name> jcmd 1 GC.heap_dump /tmp/docker.hprof

В основном он выгружает кучу процесса с помощью pid = 1, используя jcmd

См. https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

Ответ 5

Что произойдет, если вы просто запустите

./jmap -heap 11175 

И вы уверены, что приложение JVM идентично JMAP JVM? (та же версия и т.д.)

Ответ 6

Я получил ту же ошибку jmap на Linux-машине, у которой установлены два разных OpenJdks. Сначала я установил OpenJDK 1.6 и после этого OpenJDK 1.7.

Вызов...

/usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -XshowSettings:properties -version

# produce the following output ...
...
java.library.path = /usr/java/packages/lib/amd64
    /usr/lib/x86_64-linux-gnu/jni
    /lib/x86_64-linux-gnu
    /usr/lib/x86_64-linux-gnu
    /usr/lib/jni
    /lib
    /usr/lib
...
java version "1.7.0_65"

С включением '/usr/lib' каждый с OpenJDK 1.7. * запущенная программа включает в себя библиотеки первого установленного JDK (в моем случае OpenJDK 1.6. *). Таким образом, jmap-версии Java6 и Java7 не удались.

После того, как я изменил старт для Java7-программ с включенными библиотеками OpenJDK 1.7...

/usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -Djava.library.path=/usr/lib/jvm/java- \
                  7-openjdk-amd64/jre/lib/amd64/server:/usr/java/packages/lib/amd64: \
                  /usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/ \
                  x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib ...

Мне удалось получить доступ к версии Java-версии jmap-программы. Но для этого требуется sudo.

Ответ 7

Вам нужно использовать jmap, который поставляется с JVM.

Ответ 8

Что сработало для меня было просто выдать команду с sudo, как в:

sudo jmap -heap 21797

Ответ 9

У меня такая же проблема, я пытаюсь найти утечку памяти в процессе, запущенном внутри контейнера Docker. Я не смог использовать jmap, вместо этого я использовал это:

jcmd <pid> GC.class_histogram 

Это дает вам список объектов в памяти. И из документации Oracle:

Рекомендуется использовать последнюю утилиту jcmd вместо утилиты jmap для расширенной диагностики и снижения издержек производительности. https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks004.html

Ответ 10

Следуйте приведенным ниже инструкциям, чтобы взять поток и кучи кучи из контейнера докеров

  • Запустите команду ниже bash в контейнер. Пожалуйста, измените CONTAINER_NAME соответствующим образом.
   docker exec -it CONTAINER_NAME bash
  1. Затем введите jps, чтобы найти все детали приложения Java и извлечь PID для вашего приложения.
jps
  1. Затем запустите команду ниже, чтобы получить дамп потока. Пожалуйста, измените PID соответствующим образом

    jstack PID > threadDump.tdump 
    
  2. Затем запустите команду ниже, чтобы получить дамп кучи. Пожалуйста, измените PID соответствующим образом

    jmap -dump:live,format=b,file=heapDump.hprof PID 
  1. Затем выйдите из контейнера докера и загрузите threadDump.tdump и heapDump.hprof из контейнера докера, выполнив команду ниже. Пожалуйста, измените CONTAINER_NAME соответствующим образом.
 sudo docker cp CONTAINER_NAME:threadDump.tdump .
 sudo docker cp CONTAINER_NAME:heapDump.hprof .

Ответ 11

1.Execute "Docker ps", will give the container Id of all services and collect the container id foe TSC.
2.Execute "docker exec -it CONTAINER_ID bash" (replace CONTAINER_ID with TSC Container id)
3.Bash will come and then execute the "jps" on bash, that will give you the PID for process(it will be 1 for jar)
4.Execute the "jstack PID > threadDump.tdump"(replace PID with process id received in step 3, it should be 1)
5.Execute the "jmap -dump:format=b,file=heapDump.hprof PID"(replace PID with process id received in step 3, it should be 1)
6.Then we have to exit the bash using "exit" command
7.Execute "sudo docker cp CONTAINER_ID:heapDump.hprof ." from ec2 command line, that will copy the dump file on ec2 machine present working directory.
8.Execute "sudo docker cp CONTAINER_ID:threadDump.tdump ." from ec2 command line, that will copy the dump file on ec2 machine present working directory.

Ответ 12

Если ни одна из этих функций не работает или вы не хотите изменять уязвимые флагов ОС, такие как ptrace_scope:

Либо вы можете использовать jconsole/jvisualvm для триггерных дампов кучи или запустить любого JMX-клиента прямо с консоли, как показано ниже, так как вы делаете это локально на машина, которая нуждается в дампе, и так быстрее:

echo 'jmx_invoke -m com.sun.management:type=HotSpotDiagnostic dumpHeap heapdump-20160309.hprof false' | java -jar jmxsh.jar -h $LOCALHOST_OR_IP -p $JMX_PORT

Я использовал wget https://github.com/davr/jmxsh/raw/master/jmxsh.jar для этого примера.