java - 如何使用 Java 中基于信号处理的机制将 JNI 崩溃捕获为异常

标签 java c exception java-native-interface signal-handling

我开发了一个Java工具,它有很多JNI函数,我经常遇到JNI崩溃的情况。是否有可能避免这些崩溃或将这些崩溃捕获为异常。我上网发现可以通过信号处理、信号 channel 、sigaction()等来实现。但我找不到可靠的来源来指导我。请在这方面指导我。

最佳答案

JNI 异常被视为信号。您可以通过 sigaction 设置信号处理程序,然后尝试展开崩溃堆栈,例如通过 libcorkscrew ,将其保存在磁盘上。之后,您可以通过 JNI 接口(interface)调用 Java 方法来处理您保存的信息。

示例:

int watched_signals[] = { SIGABRT, SIGILL, SIGSEGV, SIGINT, SIGKILL };

void sighandler_func(int sig, siginfo_t* sig_info, void* ptr)
{
    // Dump the callstack by libcorkscrew
    ...
    // Call a JNI interface to process the stack info
    ...
}

struct sigaction sighandler;
sighandler.sa_sigaction = &sighandler_func;
sighandler.sa_mask = 0;
sighandler.sa_flags = SA_SIGINFO | SA_ONSTACK;

for(int signal : watched_signals)
{
    sigaction(signal, &sighandler, nullptr);
}

假设您已将 libcorkscrew 纳入您的 ndk 项目中,那么您可以获得崩溃堆栈:

#include <dlfcn.h>
#include <ucontext.h>
#include <corkscrew/backtrace.h>
#include <backtrace-arch.h>

void dump_stack(int sig, siginfo_t* sig_info, void* ptr)
{
    const size_t BACKTRACE_FRAMES_MAX = 0xFF;

    static backtrace_frame_t frames[BACKTRACE_FRAMES_MAX];
    static backtrace_symbol_t symbols[BACKTRACE_FRAMES_MAX];

    map_info_t* const info = acquire_my_map_info_list();
    const ssize_t size = unwind_backtrace_signal_arch(sig_info, ptr, info, frames, 0, BACKTRACE_FRAMES_MAX);
    get_backtrace_symbols(frames, size, symbols);

    for (int i = 0; i < size; i++)
    {
        backtrace_symbol_t& symbol = symbols[i];
        // You could change the printf to fwrite if you want to save the info on disk
        printf("#%02d pc %08X  %s (%s+%d)",
                    i,
                    symbol.relative_pc,
                    symbol.map_name ? symbol.map_name : "<unknown>",
                    symbol.demangled_name ? symbol.demangled_name : symbol.symbol_name,
                    symbol.relative_pc - symbol.relative_symbol_addr);
    }
    free_backtrace_symbols(symbols, size);
    release_my_map_info_list(info);
}

即使您可以在处理信号后继续该程序,但我强烈建议您将信息保存在磁盘上并在下一次应用程序启动时处理它。因为大多数时候,当信号发出时,你的程序就会失败。

关于java - 如何使用 Java 中基于信号处理的机制将 JNI 崩溃捕获为异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30105719/

相关文章:

java - Hibernate 4 默认事务超时值

java - 创建变更集时出错 - "DependsOn must be a string or list of strings."

java - Elasticsearch 更像这样的结果

C语言将char数组转换成int二维数组

c - FlexeLint 在 va_list 上抛出错误

Java:守护进程:thread.join() 未完成,之前在一个线程中抛出异常

java - 为复合整数键实现 hashCode()

c++ - 如何将未经预处理的 C/C++ 源代码转换为语法树(并返回)?

java - 为什么我的 `main()` 没有捕获在 junit 测试中 `timer` 中抛出的异常?

c++ - 使用 std::runtime_error 而不是 CException