一、java层未处理异常
未处理异常定义:没有被try…catch 住的异常(这里说的异常包括Exception和Error) Java层默认未处理异常的Handler,都是调用Thread.setDefaultUncaughtExceptionHandler,注册一个UncaughtExceptionHandler来实现的。可以抓到所有线程的未处理异常
final Thread.UncaughtExceptionHandler oldHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
// 编写崩溃前的处理逻辑
// ...
// 此回调既可以收到Exception, 也可以收到Error
/*调用默认处理,杀死进程*/
oldHandler.uncaughtException(thread, throwable);
}
});
当然也可以注册针对指定线程的未处理异常的Handler,如:
Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
// 编写崩溃前的处理逻辑
// ...
// 此回调既可以收到Exception, 也可以收到Error
if( /*这是一个致命错误*/ ) {
//调用默认处理,杀死进程
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(thread, throwable);
} else {
// 什么也不处理的话, 当前线程被终止,但是整个进程可以继续运行
}
}
});
另外发现,有一种捕获不到的exception,可以尝试adb log捕获所有信息,然后删选有用信息
二、native层异常
native异常是通过信号来通知的。所以要想抓到native异常,需要注册信号回调。
注册方法:
static struct sigaction g_oldCSSigAction[8] = {0};
void CrashSaver_handleSignal(int sig, siginfo_t* info, void* context);
// 注册信号函数
void CrashSaver_install()
{
// 保存信号的默认行为对象
memset(g_oldCSSigAction, 0, sizeof(g_oldCSSigAction));
sigaction(SIGTRAP, NULL, &g_oldCSSigAction[0]);
sigaction(SIGABRT, NULL, &g_oldCSSigAction[1]);
sigaction(SIGILL, NULL, &g_oldCSSigAction[2]);
sigaction(SIGSEGV, NULL, &g_oldCSSigAction[3]);
sigaction(SIGFPE, NULL, &g_oldCSSigAction[4]);
sigaction(SIGBUS, NULL, &g_oldCSSigAction[5]);
sigaction(SIGPIPE, NULL, &g_oldCSSigAction[6]);
sigaction(SIGSYS, NULL, &g_oldCSSigAction[7]);
// 创建 信号行为对象
struct sigaction newSigAction;
sigemptyset(&newSigAction.sa_mask);
newSigAction.sa_flags = SA_SIGINFO;
/*设置信号处理函数*/
newSigAction.sa_sigaction = CrashSaver_handleSignal;
// 注册信号新的行为对象
sigaction(SIGTRAP, &newSigAction, NULL);
sigaction(SIGABRT, &newSigAction, NULL);
sigaction(SIGILL, &newSigAction, NULL);
sigaction(SIGSEGV, &newSigAction, NULL);
sigaction(SIGFPE, &newSigAction, NULL);
sigaction(SIGBUS, &newSigAction, NULL);
sigaction(SIGPIPE, &newSigAction, NULL);
sigaction(SIGSYS, &newSigAction, NULL);
}
编写回调处理函数:
void CrashSaver_handleSignal(int sig, siginfo_t* info, void* context)
{
// sig 触发的信号ID 如 SIGABRT、SIGSEGV等
// info 对此信号的描述信息
// context 信号发生的上下文。比如各种寄存器信息。此结构和具体的CPU平台有关
// 此处增加处理逻辑
CrashSaver_uninstall(); /*反注册*/
raise(signum); /*调用系统默认信号处理*/
}
反注册函数:
void CrashSaver_uninstall()
{
sigaction(SIGTRAP, &g_oldCSSigAction[0], NULL);
sigaction(SIGABRT, &g_oldCSSigAction[1], NULL);
sigaction(SIGILL , &g_oldCSSigAction[2], NULL);
sigaction(SIGSEGV, &g_oldCSSigAction[3], NULL);
sigaction(SIGFPE, &g_oldCSSigAction[4], NULL);
sigaction(SIGBUS, &g_oldCSSigAction[5], NULL);
sigaction(SIGPIPE, &g_oldCSSigAction[6], NULL);
sigaction(SIGSYS, &g_oldCSSigAction[7], NULL);
memset(g_oldCSSigAction, 0, sizeof(g_oldCSSigAction));
}