使用Java JNI时是否可以调试核心转储?

 2023-01-19    357  

问题描述

我的应用程序主要是Java,但对于某些计算,使用C ++库.我们的环境是Java 1.6在Redhat 3上运行(即将为Redhat 5).

我的问题是C ++库不是线程安全.为了解决这个问题,我们运行多个单线读取”工人”流程,并让他们从中央工作经理(也用C ++编写的中央工作经理)进行工作.我们的Java应用程序通过第三方产品致电C ++工作经理.

使用Java JNI时是否可以调试核心转储?

由于各种原因,我们要重写C ++工作经理和工人.我赞成在Java中写所有这些,使用每个工人中的JNI致电C ++库.

主要问题是如果C ++库核心转储会发生什么.不幸的是,这很普遍,我们需要能够查看我们的C ++库中的哪一行引起的问题,例如通过检查诸如GDB之类的回溯.

我的同事认为,不可能分析核心转储,因为诸如GDB之类的工具不了解Java生成的核心文件.

我希望他们错了,但是在进一步推动我的想法之前,我需要确定.

分析由Java/jni产生的核心转储的最佳方法是什么?

推荐答案

是的,有.每次JVM崩溃,因为JNI部件中的SigSeGV,您都会在$ JAVA_HOME/BIN目录中获得带有Core Dump的文件.它通常名称hs_err_pid.log.

您可以获得更多信息/a>,and 在这里 . 在这里是一个有点相关的stackoverflow问题.

其他推荐答案

要将核心文件读取到GDB中,您必须将Java虚拟机添加到它.那是

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

很可能会告诉您找不到大量符号(正常,这些是JVM符号).但是,如果您键入” BT”,则崩溃的JNI调用可能会出现在您的StackTrace中.一个例子,在我的情况下,我写的本地库中发生了崩溃,是:

(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

以上所述是小编给大家介绍的使用Java JNI时是否可以调试核心转储?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/25829.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。