在 64 位下调用 throw 时,JNI 代码因核心转储而崩溃 [英] JNI code crash with core dump when throw is called under 64 bit

查看:17
本文介绍了在 64 位下调用 throw 时,JNI 代码因核心转储而崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 java + c++(使用 JNI),我必须加载自己的本机库,但是当调用 throw 时应用程序因核心转储失败,尽管代码被异常处理程序包围(请参阅下面的代码).这是相同的代码,在 linux 64 位、sparc 64 位和 i386 32 位上没有问题.

I'm working with java + c++ ( using JNI ) and i must load own native libraries but application failed with core dump when throw is called lthough the code is surrounded by an exception handler (see code below). It's the same code working without problem on linux 64bit, sparc 64bit and i386 32bit.

尝试在 intel SunOs 上运行 java 8 下的应用程序时出现问题.

The problem occurred when trying to run an application under java 8 on intel SunOs.

标记 -m64 已添加到 Makefile,库已添加到 LD_PRELOAD_64 并且 LD_LIBRARY_PATH_64 已正确设置.

The flag -m64 has been added to the Makefile and library was added to the LD_PRELOAD_64 and LD_LIBRARY_PATH_64 has been set correctly.

java启动,成功加载库并运行本机代码(Java_com_jnetx_usw_chp_CHPMain_start)并抛出崩溃:

The java starting, successfully load library and run the native code (Java_com_jnetx_usw_chp_CHPMain_start) and crash on the throw:

INF:17:59:33.20:CHP main(27): CHPMain.run: ok load chp library. Start it...
NOT:17:59:33.22:CHP main(27): CHPMain.run: -> chp.start
Wed Nov  8 17:59:34  CHP::startTest : cycle = 1
Wed Nov  8 17:59:35  CHP::startTest : cycle = 2
Wed Nov  8 17:59:35  Try cause Exception... 
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000000012ab5, pid=10081, tid=0x0000000000000026
#
# JRE version: Java(TM) SE Runtime Environment (8.0_121-b13) (build 1.8.0_121-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode solaris-amd64 compressed oops)
# Problematic frame:
# C  0x0000000000012ab5
#
# Core dump written. Default location: /home/kcc_64/x2001/bin/core or core.10081
#
# An error report file with more information is saved as:
# /home/kcc_64/x2001/bin/hs_err_pid10081.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

原生代码

JNIEXPORT void JNICALL Java_com_jnetx_usw_chp_CHPMain_start
  (JNIEnv *env, jobject jobj, jint trc_level,jobjectArray j_argv,jobject chp_main,jobject chp_smp)
{
    chp = new CHP();
    chp->startTest();
}

void CHP::startTest() {
    int t = 1;

    while (true) {
        try {
            poll(NULL, 0, 1000);
            fprintf(stderr, "%s CHP::startTest : cycle = %d
", getTime(), t++);

            if ( 3 == t ) {
                fprintf(stderr, "%s :  Try generate Exception... 
", getTime());
                throw 20;
            }
        }
        catch (const int & e) {
            fprintf(stderr, "%s :  Catch, e = %d
", getTime(), e);
            break;
        }
        catch (...) {
            fprintf(stderr, "%s : Catch unknown exception...
", getTime());
            break;
        }
    }
    fprintf(stderr, "%s :  CHP::startTest : End thread, exit
", getTime());
}

为什么忽略 catch 块,然后我们立即转到以核心转储结束的系统信号处理程序(参见下面的 pstack)?

Why the catch block is ignored and immediately we go to the system signal handler which ends with core dump (see pstack below)?

-bash-3.00$ uname -aSunOS x2001 5.10 Generic_142910-17 i86pc i386 i86pc-bash-3.00$ pstack 核心

-bash-3.00$ uname -a SunOS x2001 5.10 Generic_142910-17 i86pc i386 i86pc -bash-3.00$ pstack core

-bash-3.00$ gcc --version海湾合作委员会(海湾合作委员会)4.4.2版权所有 (C) 2009 Free Software Foundation, Inc.这是免费软件;请参阅复制条件的来源.没有保修单;甚至不是为了特定目的的适销性或适用性.

-bash-3.00$ gcc --version gcc (GCC) 4.4.2 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

pflags core
/38:   flags = DETACH
        sigmask = 0xfffffeff,0x0000ffff  cursig = SIGABRT

pstack core
 fffffd7fff291aea _lwp_kill () + a
 fffffd7fff236c39 raise () + 19
 fffffd7fff215bb0 abort () + 90
...
 fffffd7ffe9d0343 JVM_handle_solaris_signal () + 8d7
 fffffd7ffe9c8617 signalHandler () + 2f
 fffffd7fff28c2e6 __sighndlr () + 6
 fffffd7fff280bc2 call_user_handler () + 252
 fffffd7fff280dee sigacthandler (b, fffffd7f7e2f5208, fffffd7f7e2f4ea0) + ee
 --- called from signal handler with signal 11 (SIGSEGV) ---
 0000000000013dd5 ???????? () + 28000d930d5
 fffffd7fff2904d9 _SUNW_Unwind_RaiseException () + 46
 fffffd7f7dea2c53 __cxa_throw () + 9b                      !!!!!!!!!
 fffffd7f7f213310 _ZN3CHP9startTestEv () + 190
 fffffd7fee215a14 * com/jnetx/usw/chp/CHPMain.start(I[Ljava/lang/String;Lcom/jnetx/usw/chp/CHPMain;Lcom/jnetx/usw/chp/CHPSmp;)V+0
 fffffd7fee2083b6 * com/jnetx/usw/chp/CHPMain.run([Ljava/lang/String;Lcom/jnetx/usw/chp/CHPUpdateListener;)V+563 (line 377)
 fffffd7fee2083b6 * com/jnetx/usw/chp/CHPProvider$1.run()V+20 (line 374)
 fffffd7fee2007a7 * com/jnetx/usw/chp/CHPProvider$1.run()V+17760
 fffffd7ffe4c10ff __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ () + 8d7
 fffffd7ffe4bcd3c __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_pnGSymbol_5pnRJavaCallArguments_pnGThread__v_ () + 424
 fffffd7ffe4bd124 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_pnGSymbol_6pnGThread__v_ () + 60
 fffffd7ffe64030c __1cMthread_entry6FpnKJavaThread_pnGThread__v_ () + b8
 fffffd7ffebd9679 __1cKJavaThreadDrun6M_v_ () + 5e1
 fffffd7ffe9bdc85 java_start () + 175
 fffffd7fff28bfbb _thr_setup () + 5b
 fffffd7fff28c1e0 _lwp_start ()

推荐答案

问题已解决:

存在一个已知问题,即这两者之间的 ABI 略有不匹配(libgcc_s.so:_Unwind_RaiseException 和 Solaris libc.so:_Unwind_RaiseException).将符号绑定到 GCC 运行时首先使其在 Solaris 运行时之前加载,并且一切正常.但是,简单地将其显式添加到我们的共享库链接行没有任何帮助.

There is a known issue with a slight mismatch in the ABI between these two (libgcc_s.so: _Unwind_RaiseException and Solaris libc.so: _Unwind_RaiseException). Binding symbols to the GCC runtime first causes it to be loaded before the Solaris runtime, and everything works out well. But, simply adding this explicitly to our shared library link line did not help anything.

所以我的简单解决方法帮助了我:

so my simple workaround helped me:

LD_PRELOAD=/usr/sfw/lib/amd64/libgcc_s.so

主要原因是gcc的版本,我用的是4.4,但是4.9已经修复了-在 64 位 Solaris 10+/x86 上混合使用 libc 和 libgcc_s 展开器会破坏 EHhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788

The main reason has been in the version of gcc, i used 4.4, but fix has been made in 4.9 - Mixing libc and libgcc_s unwinders on 64-bit Solaris 10+/x86 breaks EH https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788

这篇关于在 64 位下调用 throw 时,JNI 代码因核心转储而崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆