You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Java核心转储获取自研JNI库的错误行号?

如何从Java核心转储中获取自研JNI库的错误行号?

问题背景

想要从Java核心转储(或hs_err日志)中获取自研JNI库的错误行号,以下是不同JVM参数下的hs_err日志片段(AMIn2_*为自研C函数名):

日志示例1

$ grep AMIn2 /tmp/hs_err_pid3688886.log
J 11555  net.hep.ami.utility.n2edm.AMIreadN2DataJNI.AMIn2_GetRunNumbersJSON(Ljava/lang/String;I)Ljava/lang/String; (0 bytes) @ 0x00007f003d64e3fa [0x00007f003d64e3a0+0x000000000000005a]

日志示例2(添加了-XX:+UnlockDiagnosticVMOptions和-XX:+ShowHiddenFrames)

$ grep AMIn2 /tmp/hs_err_pid1598986.log
j  net.hep.ami.utility.n2edm.AMIreadN2DataJNI.AMIn2_GetSubsystemsJSON(Ljava/lang/String;II)Ljava/lang/String;+0
j  net.hep.ami.utility.n2edm.AMIreadN2Data.AMIn2_GetSubsystemsJSON(Ljava/lang/String;II)Ljava/lang/String;+3
R13={method} {0x00007f20f8ba29f8} 'AMIn2_GetSubsystemsJSON' '(Ljava/lang/String;II)Ljava/lang/String;' in 'net/hep/ami/utility/n2edm/AMIreadN2DataJNI'
stack at sp + 4 slots: 0x00007f21100a7fea: AMIn2_GetSubsystemsJSON+0x000000000000022d in /opt/AMI/externalLib/libAMIreadN2Data_swig.so at 0x00007f211009c000

尝试了以下addr2line命令但未得到有效结果:

$ addr2line -e lib*_swig.so -a 0x00007f20f8ba29f8 
0x00007f20f8ba29f8
??:0

$ addr2line -e lib*_swig.so -f -C 0x00007f20f8ba29f8 
??
??:0

疑问:是否需要加减基地址?如何在核心转储中找到基地址?


解决方法

1. 错误原因:用错了地址

你传入addr2line的0x00007f20f8ba29f8是Java方法的内存地址,不是JNI库中C函数的实际执行地址,因此无法解析出行号。

2. 提取正确的C函数地址

从日志示例2的stack at sp + 4 slots行中,能获取关键信息:

  • JNI库的加载基地址:0x00007f211009c000(日志末尾的at 0x...部分)
  • C函数的绝对执行地址:0x00007f21100a7fea
  • 函数入口的偏移量:AMIn2_GetSubsystemsJSON+0x22d(相对于函数入口的偏移)

3. 正确使用addr2line

方法一:计算相对偏移后解析

先计算绝对地址相对于库基地址的偏移:

0x00007f21100a7fea - 0x00007f211009c000 = 0x9fea

然后用这个相对偏移执行addr2line:

addr2line -e libAMIreadN2Data_swig.so -f -C 0x9fea

方法二:直接用绝对地址(部分addr2line版本支持)

如果你的addr2line支持解析绝对地址,可以直接传入:

addr2line -e libAMIreadN2Data_swig.so -f -C 0x00007f21100a7fea

4. 如何获取JNI库的基地址

  • 从hs_err日志获取:查看日志中的Loaded Libraries区块,里面会列出所有加载的库及其基地址,比如你的日志已经给出了libAMIreadN2Data_swig.so的基地址。
  • 从核心转储获取:用gdb加载核心转储后查看:
    gdb <你的Java可执行文件路径> <核心转储文件路径>
    (gdb) info sharedlibrary libAMIreadN2Data_swig.so
    
    输出中会显示库的加载基地址。

5. 关键前提:编译JNI库时生成调试信息

必须确保编译JNI库时添加了-g参数(GCC)或对应调试参数,否则即使地址正确,addr2line也无法解析出具体的行号。


内容的提问来源于stack exchange,提问作者dargaud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:13:24