8


6

Java JNIを使​​用しているときにコアダンプをデバッグすることは可能ですか?

私のアプリケーションはほとんどがJavaですが、特定の計算ではC ++ライブラリを使用します。 私たちの環境は、RedHat 3(まもなくRedHat 5)で実行されるJava 1.6です。

私の問題は、C ライブラリがスレッドセーフではないことです。 これを回避するために、複数のシングルスレッドの「ワーカー」プロセスを実行し、C で記述された中央のワークマネージャーから実行できるようにします。 Javaアプリケーションは、サードパーティ製品を介してC ++ Work Managerを呼び出します。

さまざまな理由から、C Work Managerとワーカーを書き直したいと考えています。 すべてのJavaで記述し、各ワーカーでJNIを使​​用してC ライブラリを呼び出すことに賛成です。

主な問題は、C ライブラリがダンプした場合に何が起こるかです。 残念ながら、これは非常に一般的であり、C ライブラリのどの行が問題を引き起こしたかを確認する必要があります。 GDBのようなものでバックトレースを調べることによって。

私の同僚は、GDBのようなツールはJavaによって生成されたコアファイルを理解しないため、コアダンプを分析することは不可能だと考えています。

それらが間違っていることを願っていますが、アイデアをさらに進める前に確認する必要があります。

Java / JNIから生成されたコアダンプを分析する最良の方法は何ですか?

2 Answer


8


はいあります。 JNI部分のSIGSEGVが原因でJVMがクラッシュするたびに、$ JAVA_HOME / binディレクトリにコアダンプのファイルが作成されます。 通常、hs_err_PID.logという名前です。

詳細については、http://weblogs.java.net/blog/kohsuke/archive/2009/02/crash%5Fcourse%5Fon.html [こちら]およびhttp://java.sun.com/javase/6をご覧ください。 /webnotes/trouble/TSG-VM/html/felog.html [こちら]。 https://stackoverflow.com/questions/592520/how-do-i-interpret-this-jvm-fault [こちら]はやや関連するstackoverflowの質問です。


3


コアファイルをgdbに読み込むには、Java仮想マシンを追加する必要があります。 あれは

gdb /usr/local/jdk1.8.0_66/bin/java core

非常に多くのシンボルが見つかりません(通常、JVMシンボルです)。 ただし、「bt」と入力すると、クラッシュしたJNI呼び出しがスタックトレースに表示される場合があります。 私が書いたネイティブライブラリでクラッシュした私の状況での例は次のとおりです。

(gdb) bt
#0  0x00007fd61dfcd107 in __GI_raise ([email protected]=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007fd61dfce4e8 in __GI_abort () at abort.c:89
#2  0x00007fd61d8d3795 in os::abort(bool) ()
   from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so
#3  0x00007fd61da71e23 in VMError::report_and_die() ()
   from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so
#4  0x00007fd61d8d8fbf in JVM_handle_linux_signal ()
   from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so
#5  0x00007fd61d8cf753 in signalHandler(int, siginfo*, void*) ()
   from /usr/local/jdk1.8.0_66/jre/lib/amd64/server/libjvm.so
#6

最初の6フレームはすべて、クラッシュプロセス自体に関連しています。 シグナルがキャッチされ、ディスパッチされました。 そして、正確な機能はわかりませんが、問題ではありません。 フレーム7から、私たちは書いたJNIライブラリにいます。 また、シンボルがまだ添付されている場合は、それらが表示されます。

#7  0x00007fd5ff43bf7e in FftResampler::resample(Complex const*, int)
    ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#8  0x00007fd5ff43ddcf in TimeStretcher::rescaleEnvelopeSlow(PeakMap const*, Peak*) ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#9  0x00007fd5ff43e4a5 in TimeStretcher::transferPeak(Frame*, Frame*)
    ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#10 0x00007fd5ff43e679 in TimeStretcher::transferPeaks(Channel*) ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#11 0x00007fd5ff43eb3a in TimeStretcher::putStereo(float const*, int)
    ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#12 0x00007fd5ff43edbf in TimeStretcher::processStereo(float const*, int, float*) ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so
#13 0x00007fd5ff43b45d in Java_org_yellowcouch_bpmdj_mixedit_audio_JavaTimeStretcher_processStereo ()
   from /I/home/werner/BpmDj/NextGen/Beta/Desktop/test/libzathras-46703-64.so

そして、フレーム14からはJavaの土地に戻りました。

#14 0x00007fd6097a29e1 in ?? ()
#15 0x00007fd5d6ee6580 in ?? ()
#16 0x00000000853f53e8 in ?? ()
#17 0x00000000d803c340 in ?? ()
#18 0x00000000d80564e8 in ?? ()
#19 0x00007fd61e773609 in _L_unlock_554 ()
   from /lib/x86_64-linux-gnu/libpthread.so.0

したがって、gdbを使用してコアファイルから情報を取得することは完全に不可能ではないことがわかります。 jvmを最初の引数として追加することを忘れないでください。

gdbがネイティブライブラリ自体を見つけられない可能性があります。 その場合、次のようにシンボルを手動でロードできます。

gdb>シンボルファイルlibzathras-46703-64.so

さらに詳しい情報が必要な場合は、デバッグ情報をオンにしてc / c ++コードをコンパイルすることをお勧めします。 通常、mingwおよびgccコンパイラーでは、コマンドラインオプションに-gを追加します。 これにより、行番号などを含む次の情報が提供されます。

#7  FftResampler::resample ([email protected]=0x7f4bf8f36100,
    [email protected]=0x7f4bf8ed1ea0, n=)
    at timestretcher.cpp:347
#8  0x00007f4c51605dcf in TimeStretcher::rescaleEnvelopeSlow (
    this=0x7f4bf8ec1e10, table=0x7f4bf90f4c20, borders=0x7f4bf8fd27a0)
    at timestretcher.cpp:878
#9  0x00007f4c516064a5 in TimeStretcher::transferPeak (
    [email protected]=0x7f4bf8ec1e10,
    [email protected]=0x7f4bf8fde6f0,
    [email protected]=0x7f4bf8fb2650) at timestretcher.cpp:718
#10 0x00007f4c51606679 in TimeStretcher::transferPeaks (
    [email protected]=0x7f4bf8ec1e10,
    [email protected]=0x7f4bf8ec9e90) at timestretcher.cpp:687
#11 0x00007f4c51606b3a in TimeStretcher::putStereo (
    [email protected]=0x7f4bf8ec1e10, [email protected]=0x7f4bf8eb9e00,
    [email protected]=-1395) at timestretcher.cpp:1483
#12 0x00007f4c51606dbf in TimeStretcher::processStereo (
    [email protected]=0x7f4bf8ec1e10, [email protected]=0x7f4bf8eb9e00,
    [email protected]=-1395, out=0x7f4bf90f4c60)
    at timestretcher.cpp:1567
#13 0x00007f4c5160345d in Java_org_yellowcouch_bpmdj_mixedit_audio_JavaTimeStretcher_processStereo (env=0x7f4bf90f71f8, obj=,
    handle=139964275465728, in=0x7f4bed136468, inIdx=,
    time=-1395, out=0x7f4bed136480) at timestretcher-jni.cpp:69