2009-11-19 3 views
7

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

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

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

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

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

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

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

ответ

7

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

Вы можете получить дополнительную информацию here и here. Here - это несколько связанный с этим вопрос stackoverflow.

+2

Спасибо, Пабло. статья kohsuke превосходна. К сожалению, если я скажу своим коллегам, что им нужно понять ассемблер, чтобы выяснить, какая линия C++ вызвала ошибку seg, они пробегут милю. Я нахожусь в Linux, и мои файлы .so были скомпилированы с включенным флагом отладки. Возможно, это облегчит процесс. –

+1

Извините, но файл «log» не имеет ничего общего с вопросом о том, как запросить O.P. – 2016-01-29 11:23:12

+0

Я нашел эти файлы hs_err_PID в каталоге/tmp. – Aman

2

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

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

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

(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> symbol-file 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' с адресом из дампа, чтобы получить точную строку кода, вызывающую проблему. – Shark