2009-11-19 91 views
7

我的應用程序主要是Java,但在某些計算中使用C++庫。我們的環境是在RedHat 3上運行的Java 1.6(即將成爲RedHat 5)。使用Java JNI時可以調試核心轉儲嗎?

我的問題是,C++庫不是線程安全的。爲了解決這個問題,我們運行多個單線程「工作」進程,並讓他們從一箇中央工作管理器開始工作,這個工作管理器也是用C++編寫的。我們的Java應用程序通過第三方產品調用C++ Work Manager。

由於各種原因,我們希望重新編寫C++工作管理器和工作人員。我贊成用Java編寫它們,在每個worker中使用JNI來調用C++庫。

主要問題是如果C++庫核心轉儲會發生什麼情況。不幸的是,這是很常見的,我們需要能夠看到C++庫中的哪一行導致了問題,例如通過檢查諸如GDB之類的回溯。

我的同事們相信,這將是不可能的分析核心轉儲,因爲像GDB工具,不明白在Java生成的核心文件。

我希望他們錯了,但我還需要進一步推動我的想法之前,請確保。

什麼是分析從Java/JNI產生一個核心轉儲的最佳方式?

回答

7

是的,有。每當JVM由於JNI部分中的SIGSEGV而崩潰時,您將在$ JAVA_HOME/bin目錄中獲得一個包含核心轉儲的文件。它通常命名爲hs_err_PID.log。

你可以得到更多的信息here,和hereHere是一個有點相關的stackoverflow問題。

+2

謝謝巴勃羅。 kohsuke的文章非常好。不幸的是,如果我告訴我的同事他們需要了解彙編程序來發現哪個C++線路導致了seg故障,那麼它們將運行一英里。 我在Linux上,並且我的.so文件已經在打開調試標誌的情況下編譯。也許這會讓這個過程變得更簡單。 – 2009-11-19 14:48:47

+1

對不起,但是一個'日誌'文件與O.P詢問的coredump沒有任何關係。 – 2016-01-29 11:23:12

+0

我在/ tmp目錄中找到了這些hs_err_PID文件。 – Aman 2016-04-26 08:35:35

2

要將核心文件讀入gdb,必須將java虛擬機添加到gdb中。這是

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 <signal handler called> 

第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。所以

如果你想要更多的信息,你可能想編譯你的c/c + +代碼打開調試信息。通常在使用mingw和gcc編譯器時,可以在命令行選項中添加-g。這將爲您提供以下信息,其中包括行號等。

#7 FftResampler::resample ([email protected]=0x7f4bf8f36100, 
    [email protected]=0x7f4bf8ed1ea0, n=<optimized out>) 
    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=<optimized out>, 
    handle=139964275465728, in=0x7f4bed136468, inIdx=<optimized out>, 
    time=-1395, out=0x7f4bed136480) at timestretcher-jni.cpp:69 
+0

另外,不要忘記你可以使用'addr2line'和dump中的地址來得到導致問題的確切代碼行。 – Shark 2016-01-29 12:30:00