Можно ли отлаживать дамп ядра при использовании Java JNI? - PullRequest
8 голосов
/ 19 ноября 2009

Мое приложение в основном Java, но для некоторых вычислений используется библиотека C ++. Нашей средой является Java 1.6, работающая на RedHat 3 (скоро будет RedHat 5).

Моя проблема в том, что библиотека C ++ не является поточно-ориентированной. Чтобы обойти это, мы запускаем несколько однопоточных «рабочих» процессов и даем им работу, выполняемую из центрального Work Manager, также написанного на C ++. Наше Java-приложение вызывает C ++ Work Manager через сторонний продукт.

По разным причинам мы хотим переписать C ++ Work Manager и рабочих. Я за то, чтобы писать их все на Java, используя JNI на каждом рабочем месте для вызова библиотеки C ++.

Основная проблема заключается в том, что происходит, если дамп ядра C ++ библиотеки. К сожалению, это довольно часто, и мы должны быть в состоянии увидеть, какая строка в нашей библиотеке C ++ вызвала проблему, например, исследуя обратную трассировку в чем-то вроде GDB.

Мои коллеги считают, что анализ дампов ядра будет невозможен, потому что такие инструменты, как GDB, не понимают файлы ядра, созданные Java.

Я надеюсь, что они не правы, но я должен быть уверен, прежде чем продвигать свои идеи дальше.

Каков наилучший способ анализа дампа ядра, созданного из Java / JNI?

Ответы [ 2 ]

8 голосов
/ 19 ноября 2009

Да, есть. Каждый раз, когда происходит сбой JVM из-за SIGSEGV в части JNI, вы получаете файл с дампом ядра в каталоге $ JAVA_HOME / bin. Обычно это имя hs_err_PID.log.

Вы можете получить больше информации здесь и здесь . Здесь - вопрос, связанный с переполнением стека.

4 голосов
/ 29 января 2016

Чтобы получить файл ядра для чтения в gdb, вы должны добавить к нему виртуальную машину java. Это

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

это очень вероятно скажет вам, что тонна символов не найдена (что является нормой, это символы JVM). Однако сбой вызова JNI может появиться в вашей трассировке стека, если вы введете «bt». Например, в моей ситуации, когда у меня происходит сбой в собственной библиотеке, которую я написал, это:

(gdb) bt
#0  0x00007fd61dfcd107 in __GI_raise (sig=sig@entry=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, мы снова на земле Явы.

#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 (this=this@entry=0x7f4bf8f36100, 
    cpx=cpx@entry=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 (
    this=this@entry=0x7f4bf8ec1e10, 
    prevFrame=prevFrame@entry=0x7f4bf8fde6f0, 
    frame=frame@entry=0x7f4bf8fb2650) at timestretcher.cpp:718
#10 0x00007f4c51606679 in TimeStretcher::transferPeaks (
    this=this@entry=0x7f4bf8ec1e10, 
    channel=channel@entry=0x7f4bf8ec9e90) at timestretcher.cpp:687
#11 0x00007f4c51606b3a in TimeStretcher::putStereo (
    this=this@entry=0x7f4bf8ec1e10, in=in@entry=0x7f4bf8eb9e00, 
    time=time@entry=-1395) at timestretcher.cpp:1483
#12 0x00007f4c51606dbf in TimeStretcher::processStereo (
    this=this@entry=0x7f4bf8ec1e10, in=in@entry=0x7f4bf8eb9e00, 
    time=time@entry=-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
...