SIGABRT 导致 Java 堆分析崩溃

Posted

技术标签:

【中文标题】SIGABRT 导致 Java 堆分析崩溃【英文标题】:Java heap profiling crashes with SIGABRT 【发布时间】:2019-05-20 16:37:12 【问题描述】:

我正在尝试分析由 C 编写的方法分配并插入到 JVMJNI 的本机内存。我安装了

$ valgrind --version
valgrind-3.13.0

并尝试使用以下选项运行 JVM:

valgrind --tool=massif --massif-out-file=/tmp/massif-j.out java 
    -XX:+UnlockDiagnosticVMOptions //...

问题是它在创建核心转储时崩溃

  0x00000000080e4196: fxrstor64 (%rsp)
  0x00000000080e419b: add     $0x200,%rsp
  0x00000000080e41a2: mov     (%rsp),%r15
  0x00000000080e41a6: mov     0x8(%rsp),%r14
  0x00000000080e41ab: mov     0x10(%rsp),%r13
  0x00000000080e41b0: mov     0x18(%rsp),%r12
  0x00000000080e41b5: mov     0x20(%rsp),%r11
  0x00000000080e41ba: mov     0x28(%rsp),%r10
  0x00000000080e41bf: mov     0x30(%rsp),%r9
  0x00000000080e41c4: mov     0x38(%rsp),%r8
  0x00000000080e41c9: mov     0x40(%rsp),%rdi
  0x00000000080e41ce: mov     0x48(%rsp),%rsi
  0x00000000080e41d3: mov     0x50(%rsp),%rbp
  0x00000000080e41d8: mov     0x60(%rsp),%rbx
  0x00000000080e41dd: mov     0x68(%rsp),%rdx
  0x00000000080e41e2: mov     0x70(%rsp),%rcx
  0x00000000080e41e7: mov     0x78(%rsp),%rax
  0x00000000080e41ec: add     $0x80,%rsp
  0x00000000080e41f3: add     $0x8,%rsp
  0x00000000080e41f7: Fatal error: Disassembling failed with error code: 15#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (sharedRuntime.cpp:834), pid=12441, tid=0x0000000021385700
#  fatal error: exception happened outside interpreter, nmethods and vtable stubs at pc 0x00000000080e4147
#
# JRE version: Java(TM) SE Runtime Environment (8.0_181-b13) (build 1.8.0_181-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode linux-amd64 compressed oops)
# Core dump written. Default location: /var/log/prj/core or core.12441
#
# An error report file with more information is saved as:
# /var/log/prj/hs_err_pid12441.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
==12441==
==12441== Process terminating with default action of signal 6 (SIGABRT): dumping core
==12441==    at 0x54AAE97: raise (raise.c:51)
==12441==    by 0x54AC800: abort (abort.c:79)
==12441==    by 0x658B3C4: ??? (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x672F5B2: ??? (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x615EE98: ??? (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x662A099: ??? (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x6591A49: JVM_handle_linux_signal (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x6587652: ??? (in /usr/lib/jvm/java-oracle-8-amd64/jdk/jre/lib/amd64/server/libjvm.so)
==12441==    by 0x4E4588F: ??? (in /lib/x86_64-linux-gnu/libpthread-2.27.so)
==12441==    by 0x80E4146: ???
==12441==    by 0x107: ???
==12441==    by 0x84CBC43: ???
==12441==    by 0x10001BD37: ???
==12441==    by 0xFDC7103F: ???
==12441==    by 0xA3FFFFFFFF: ???
==12441==    by 0xFF9275A7: ???
==12441==

谁能给出可能出错的想法?是因为Fatal error: Disassembling failed with error code: 15#吗?

【问题讨论】:

【参考方案1】:

具有自修改代码的 Valgrind(和基于 Valgrind 的工具)does not work well。但是,HotSpot JVM 严重依赖动态代码生成,包括覆盖和修补先前生成的指令。即使禁用 JIT 编译器也是如此,因为 HotSpot 还为解释器和运行时存根使用动态代码生成。

对于本机内存分配分析,您还可以使用jemalloc 或async-profiler。后者具有与 Java 运行时集成的优点,即它可以显示包含本机和 Java 帧的混合堆栈跟踪。此外,与虚拟化正在运行的程序的 Valgrind 不同,这两种工具的性能开销都相当小。

有关详细信息,请参阅 this 和 this 答案。

【讨论】:

我也尝试使用-fsanitize=address 编译和链接库,但不幸的是它无法捕获来自JNI 方法的简单malloc(sizeof(char)); 调用。在 JVM 下运行时使用 address sanitizer 是否有一些麻烦? @St.Antario 不,JVM 不应该影响-fsanitize=address

以上是关于SIGABRT 导致 Java 堆分析崩溃的主要内容,如果未能解决你的问题,请参考以下文章

将 [Int:String] 字典存储到 user.defaults 会因 SIGABRT 错误而崩溃

向 UIDynamicAnimator 添加超过 32 个 UIFieldBehavior 会导致 SIGABRT

Twitter登录 - 应用程序代理和应用程序崩溃中的线程1 Sigabrt错误

Webview 对象导致可可崩溃

sigabrt 没有错误信息

NSEntityDescription.entity 崩溃应用程序(SIGABRT)