Jmap не может подключиться, чтобы сделать дамп - PullRequest
49 голосов
/ 26 мая 2010

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

Чтобы проанализировать это, я хотел бы заглянуть в память в тот момент, когда это не удалось. Ява не хочет, чтобы я это делал. Процесс все еще находится в памяти, но, похоже, он не распознается как процесс 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!

Ответы [ 14 ]

2 голосов
/ 11 декабря 2014

Я получил ту же ошибку 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' every с 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 7-версии программы jmap. Но для запуска нужен sudo.

0 голосов
/ 19 августа 2018

Не уверен, почему простое "jmap" завершается неудачно, когда я docker exec -it в мой контейнер, работающий с centos7 systemd и java-сервисом, но у меня сработали опции jmap. Спасибо: https://dkbalachandar.wordpress.com/2016/07/05/thread-dump-from-a-docker-container/

[root@b29924306cfe /]# jmap 170 Attaching to process ID 170, please wait... Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 170: Operation not permitted sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 170: Operation not permitted

[root@b29924306cfe /]# jmap -dump:live,format=b,file=heapDump.hprof 170 Dumping heap to /heapDump.hprof ... Heap dump file created

0 голосов
/ 13 февраля 2018

В моем случае это не так просто, как проверить пользователя: (

У меня есть скрипт с именем collectd-java, который вызывает jstat и jmap. Я убедился, что такой скрипт запускается, как и ожидалось, пользователем, владеющим JVM. Однако jstat дает мне то, что мне нужно, а jmap не может прикрепить. Вот сценарий - эхо - это просто формат, который мне нужен для представления значений:

HOSTNAME="${COLLECTD_HOSTNAME:-localhost}"
INTERVAL="${COLLECTD_INTERVAL:-60}"
MAIN_CLASS="my.fully.qualified.MainClass"
PID=$(pgrep -f ${MAIN_CLASS})

get_jstat_classloaderdata() {
VALUE=`jstat -class $PID 1 1 | awk '{print $1}' | grep -vi loaded`
echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_loaded\" interval=$INTERVAL N:$VALUE"

VALUE=`jstat -class $PID 1 1 | awk '{print $2}' | grep -vi bytes`
echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_bytesload\" interval=$INTERVAL N:$VALUE"

VALUE=`jstat -class $PID 1 1 | awk '{print $3}' | grep -vi unload`
echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_unloaded\" interval=$INTERVAL N:$VALUE"

VALUE=`jstat -class $PID 1 1 | awk '{print $4}' | grep -vi bytes`
echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_bytesunload\" interval=$INTERVAL N:$VALUE"

VALUE=`jstat -class $PID 1 1 | awk '{print $5}' | grep -vi time`
echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_time\" interval=$INTERVAL N:$VALUE"
}

get_jmap_heapdata() {
        VALUE=$(jmap -heap ${PID} | grep MinHeapFreeRatio |awk '{print $3}')
        echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_minheapfreeratio\" interval=$INTERVAL N:$VALUE"

        VALUE=$(jmap -heap ${PID} | grep   MaxHeapFreeRatio|awk '{print $3}')
        echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_maxheapfreeratio\" interval=$INTERVAL N:$VALUE"

        VALUE=$(jmap -heap ${PID} | grep   MaxHeapSize|awk '{print $3}')
        echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_maxheapsize\" interval=$INTERVAL N:$VALUE"
}
##Do it
get_jmap_heapdata
get_jstat_classloaderdata

Jstat завершается успешно, а jmap завершается неудачей. Кто-нибудь это понимает?

0 голосов
/ 10 марта 2016

Когда ничего из этого не работает или если вы не хотите изменять чувствительные флаги ОС, такие как 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 для этого примера.

...