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

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

本文介绍了如何使用Java中基于信号处理的机制将JNI崩溃作为异常捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发了一个Java工具,它具有许多JNI功能,经常使JNI崩溃.是否有可能避免这些崩溃或将这些崩溃作为异常捕获.我上网冲浪,发现可以通过信号处理,信号调整,sigaction()等来实现.但是我找不到可靠的消息来源来指导我.请确实指导我.

I developed a Java tool and it has many JNI functions, I am getting JNI crashes often. Is there any possibility to avoid those crashes or to catch these crashes as exceptions. I surfed internet and found it is possible through signal processing, signal chanining, sigaction(), etc. But I could not get a reliable source to direct me. Please do guide me on this.

推荐答案

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

JNI exceptions are considered as signals. You could set up your signal handlers by sigaction and then you could try to unwind the crash stack, for example by libcorkscrew, to save it on the disk. After that you could invoke a Java method via JNI interfaces to process the info you saved.

示例:

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项目,则可以获取崩溃堆栈:

Suppose you have involved libcorkscrew into you ndk project then you could get the crash stack:

#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);
}

即使在您处理完信号后,您也可以继续执行该程序,但我强烈建议您将信息保存在磁盘上,并在下次启动应用程序时对其进行处理.因为大多数情况下,当信号发出时,您的编程都会失败.

Even through you could continue the program after you handled the signal but I strongly suggest you to save the info on disk and process it in the next app launch. Because most of the time you program would fail when a signal raised.

这篇关于如何使用Java中基于信号处理的机制将JNI崩溃作为异常捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 03:47