当前位置: 首页 > 知识库问答 >
问题:

在Android上用异常替换JNI崩溃

南门魁
2023-03-14

我开发了一个使用原生C库的Android应用程序。我可以成功地用JNI编译整个程序,一切都很顺利。

然而,本机C库偶尔会崩溃(最常见的是SIGSEGV)。这反过来会导致我的应用程序崩溃,而不会对用户发出任何有意义的通知。我希望实现以下目标:

  1. 使用信号处理程序(sigaction)捕获本机代码中的信号,以防止随机崩溃
  2. 在 C 库中抛出 Java 可以捕获的异常
  3. 在 Java 中捕获异常,为用户生成有意义的警告消息并保持应用运行

如果这对您有用的话——JNI代码在一个单独的线程中运行(更准确地说是在AsyncTask中)。

我已经检查了http://blog.httrack.com/blog/2013/08/23/catching-posix-signals-on-android/和https://github.com/xroche/coffeecatch,但我不能让它编译。

按照JNI代码中抛出异常的最佳方式的建议?以及如何在Java和https://www.developer.com/java/data/exception-handling-in-jni.html中使用基于信号处理的机制将JNI崩溃作为异常,我执行了以下步骤:

在我的本机代码中,我添加了以下函数(据我所知)来设置信号处理程序:

void initializeSignalHandler(JNIEnv* env){
    int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL }; // 6, 4, 11, 2, 9
    struct sigaction sighandler;
    memset(&sighandler, 0, sizeof(sighandler));

    sighandler.sa_sigaction = &sighandler_func;
    sighandler.sa_mask = 0;
    sighandler.sa_flags = SA_SIGINFO | SA_ONSTACK;
    for(int ii=0; ii<5; ii++){
        int signal = watched_signals[ii];
        sigaction(signal, &sighandler, NULL);        
    }
    env = env;
}

我处理这些信号的函数如下所示:

void sighandler_func(int sig, siginfo_t* sig_info, void* ptr){
    printerr("Sighandler: ", sig);
    jclass jcls = (*env)->FindClass(env, "java/lang/Error");
    jboolean flag = (*env)->ExceptionCheck(env);
    if (flag) {
        (*env)->ExceptionClear(env);
        /* code to handle exception */
    }
    if (jcls!=NULL){
        printerr("Throwing exception");
        (*env)->ThrowNew(env, jcls, "error message");
    }
}

我的关键JNI功能从配置信号处理程序开始:

JNIEXPORT jint JNICALL Java_android_playground_criticalFuction
    (JNIEnv *env, jclass c, jlong handle, jshortArray out_buffer){


    // new signal handler
    struct sigaction sighandler;
    initializeSignalHandler(env);

    // ...here goes the critical code
}

当SIGILL出现在我的本机C代码中时,会发生以下情况:

1)在我的调试终端上,我收到以下四条消息

  • Sighandler:4(对应于SIGILL)
  • 正在引发异常
  • Sighandler:4
  • 观景员:11

2) 应用程序窗口关闭,但我没有收到Android消息“不幸……已关闭”,这通常在应用程序崩溃时出现

我真的不明白为什么我会得到第三个和第四个信号消息,因为我会假设抛出了异常。此外,我认为异常从来没有真正抛出(到Java)。

我迷路了,非常感谢任何帮助。

共有1个答案

狄峻熙
2023-03-14

我不知道你在这里试图做的事情在技术上是否可行。@迈克尔的评论暗示这是不可能的。

但如果有可能,这是一个坏主意。

当您使用的本机库触发SIGSEGV时,它可能已经造成了不可估量的破坏;e、 g.覆盖堆中的对象等。如果您尝试恢复,则之前的损坏可能会导致意外行为或不正确的结果……或者GC稍后会由于堆损坏而崩溃。

这就是为什么当意外的SIGSEGV发生在本机代码或Java代码中时,JVM恐慌是标准行为。

虽然给用户一个有意义的错误是很好的,但是你能告诉他们的没有多少意义...如果您得到随机的SIGSEGV错误和其他JVM混乱。

 类似资料:
  • > 我正试图从Java代码调用一个C++方法 方法的签名为: > Java: 公共类FLVCamActivity扩展活动{ 静态{        System.LoadLibrary(“flvcam”);      System.out.println(“Loaded flvcam”); } 公共本机void RunFlvServer(int iCamId); C++: extern“c”JNIE

  • 我正在尝试修复崩溃,例如: 1: 2: 三: 我已经复习了IndirectReferenceTable()的源代码https://android.googlesource.com/platform/art//kitkat dev/runtime/indirect\u reference\u表。cc),它似乎因为表溢出而崩溃。 据我所知,我正在正确删除所有本地引用。 问题是否可能与当地参考文献无关?

  • 本文向大家介绍详解Android中处理崩溃异常,包括了详解Android中处理崩溃异常的使用技巧和注意事项,需要的朋友参考一下 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了崩溃现象,开发者应该及时获取在该设备上导致崩溃的信息,这对于下一个版本的

  • 本文向大家介绍Android application捕获崩溃异常怎么办,包括了Android application捕获崩溃异常怎么办的使用技巧和注意事项,需要的朋友参考一下 Android application捕获崩溃异常怎么办? 通用 application 1、收集所有 avtivity 用于彻底退出应用 2、捕获崩溃异常,保存错误日志,并重启应用 以上就是本文的全部内容,希望对大家的学习

  • 我的Android应用在使用时崩溃 这是我收到的唯一明显的错误消息: 无法将堆栈跟踪写入/data/anr/跟踪。txt(6738中的5571):没有这样的文件或目录 libMySharedLib.so 是从 ndk-build 生成的。我正在使用powerVR SDK,因此我假设这个库是事先在内部加载的。 如果我将我的代码分离到一个不同的共享库中,我可以让它工作,但这违背了我的需要(所有数据、指

  • 我正在寻找一种方法,在不让应用程序崩溃的情况下,将异常导入到解析崩溃报告管道中。 使用Parse 1.9.1,我没有看到任何API调用允许将用户生成的异常发送到崩溃报告,而不让异常崩溃应用程序。Parse已经有了一个很好的UI来显示异常,那么我为什么要推出一个解决方案来从捕获的异常中获取堆栈跟踪呢? 我尝试从一个throwable中实例化一个ParseException,但这不会隐式地导致发送崩溃