web-dev-qa-db-ja.com

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!
50
Jasper Floor

解決策は非常に簡単でした。ルートとしてjmapを実行していましたが、jvmを起動したユーザーとして実行する必要がありました。恥ずかしげに頭を隠していきます。

85
Jasper Floor

同じユーザーでjmapとアプリケーションを実行していても、エラーが発生します。

Jmapの前にコマンドが実行されたソリューション

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

Jmapを使用しているだけで問題なく動作します

jmap -heap 17210
31
jpozorio

今後のGoogle社員:

これは、jmapを実行しようとしているプロセスが実行されているときにJDKをインストールした場合whileにも発生する可能性があります。

その場合は、Javaプロセスを再起動します。

15
Ariel T

誰かが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 を参照してください

12
Oleksandr

走ったらどうなる

./jmap -heap 11175 

また、アプリケーションJVMはJMAP JVMと同一ですか? (同じバージョンなど)

6
bwawok

以下の手順に従って、ドッカーコンテナからスレッドとヒープダンプを取得します

  1. 以下のコマンドを実行して、コンテナーに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. 次に、Dockerコンテナーを終了し、以下のコマンドを実行して、DockerコンテナーからthreadDump.tdumpおよびheapDump.hprofをダウンロードします。 CONTAINER_NAMEを適切に変更してください
 Sudo docker cp CONTAINER_NAME:threadDump.tdump .
 Sudo docker cp CONTAINER_NAME:heapDump.hprof .
5
Arbaz Alam

JVMに付属のjmapを使用する必要があります。

3
ejaenv

2つの異なるOpenJdkがインストールされているLinuxマシンで同じjmapエラーが発生しました。最初に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"

OpenJDK 1.7。*に「/ usr/lib」をすべて含めると、開始プログラムには最初にインストールされたJDK(私の場合はOpenJDK 1.6。*)のライブラリが含まれます。そのため、Java6およびJava7のjmapバージョンは失敗しました。

OpenJDK 1.7ライブラリを含むJava7プログラムの開始を変更した後...

/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が必要です。

2
OkieOth

私は同じ問題を抱えています。Dockerコンテナ内で実行されているプロセスでメモリリークを見つけようとしています。私はjmapを使用できませんでしたが、代わりにこれを使用しました:

jcmd <pid> GC.class_histogram 

これにより、メモリ内のオブジェクトのリストが表示されます。 Oracleのドキュメントから:

診断を強化し、パフォーマンスのオーバーヘッドを減らすために、jmapユーティリティの代わりに最新のユーティリティであるjcmdを使用することをお勧めします。 https://docs.Oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks004.html

2
Javier Lopez
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.
2
ABHAY JOHRI

私のために働いたのは、次のようにSudoでコマンドを発行するだけでした:

Sudo jmap -heap 21797
2
CommonCoreTawan

私の場合、ユーザーを確認するほど簡単ではありません:(

Jstatとjmapを呼び出すcollectd-Javaというスクリプトがあります。そのようなスクリプトは、予想どおり、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
Zirikatzaile

これらのいずれも機能しない場合、またはptrace_scopeなどの重要なOSフラグを変更したくない場合:

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 を使用しました。

0
kisna

Centos7 systemdとJavaサービスを実行しているコンテナに_docker exec -it_)を実行すると、プレーンな "jmap"が失敗する理由はわかりませんが、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
jamshid