Android应用崩溃处理

未捕获的异常去哪里了?

在Thread.java里面有这样一个方法:

    /**
     * Set the default handler invoked when a thread abruptly terminates
     * due to an uncaught exception, and no other handler has been defined
     * for that thread.
     *
     * <p>Uncaught exception handling is controlled first by the thread, then
     * by the thread's {@link ThreadGroup} object and finally by the default
     * uncaught exception handler. If the thread does not have an explicit
     * uncaught exception handler set, and the thread's thread group
     * (including parent thread groups)  does not specialize its
     * <tt>uncaughtException</tt> method, then the default handler's
     * <tt>uncaughtException</tt> method will be invoked.
     * <p>By setting the default uncaught exception handler, an application
     * can change the way in which uncaught exceptions are handled (such as
     * logging to a specific device, or file) for those threads that would
     * already accept whatever &quot;default&quot; behavior the system
     * provided.
     *
     * <p>Note that the default uncaught exception handler should not usually
     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
     * infinite recursion.
     *
     * @param eh the object to use as the default uncaught exception handler.
     * If <tt>null</tt> then there is no default handler.
     *
     * @throws SecurityException if a security manager is present and it
     *         denies <tt>{@link RuntimePermission}
     *         (&quot;setDefaultUncaughtExceptionHandler&quot;)</tt>
     *
     * @see #setUncaughtExceptionHandler
     * @see #getUncaughtExceptionHandler
     * @see ThreadGroup#uncaughtException
     * @since 1.5
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
         defaultUncaughtExceptionHandler = eh;
     }

Uncaught exception handling is controlled first by the thread, then
* by the thread’s ThreadGroup object and finally by the default
* uncaught exception handler.

这里表明了“未捕获的异常”的处理顺序是:
1. 异常所在线程的uncaughtExceptionHandler
2. 线程所在线程组
3. Thread中的静态defaultUncaughtExceptionHandler,

经过测试和分析,这里的处理顺序是指当上一级处理了,下一级将不再进行处理

我们继续分析这个传递顺序是怎么实现的

首先,我在Thread类中找到这个方法

    /**
     * Dispatch an uncaught exception to the handler. This method is
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

这里已经明确说明了,这个方法是由JVM发起调用的。

这是异常处理发生的第一个地方

    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

来到这里,我们就可以知道,当本线程的UncaughtExceptionHandler为空时,就交给线程组来处理。

我们看看线程组是怎么处理的:

首先它实现了异常处理接口

class ThreadGroup implements Thread.UncaughtExceptionHandler

线程组处理的过程:

    public void uncaughtException(Thread t, Throwable e) {
        if (parent != null) {
            //递归交给最顶端的线程组处理
            parent.uncaughtException(t, e);
        } else {
            //获取全局的(未捕获)异常处理器
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
                //由defaultUncaughtExceptionHandler处理
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

ThreadDead的描述:

An instance of {@code ThreadDeath} is thrown in the victim thread when the (deprecated) {@link Thread#stop()} method is invoked.

按照描述,ThreadDead已经不再使用了,所以当未设置Thread.defaultUncaughtExceptionHandle时,就打印异常栈

至于应用为什么会崩溃?暂时找不到相关代码

配置自己的未捕获异常处理器(奔溃处理)

经过测试,当设置了处理器之后,android应用遇到未捕获异常时会调用我们的uncaughtException方法,而不会崩溃

一般在MyApplication中配置,也可以在主活动中进行。

//默认未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Log.d("MainActivity", "崩溃处理");
        Intent intent = new Intent(getContext(), ErrorActivity.class);
//              intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
//                      Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra("err", "应用遇到未处理的错误,即将关闭!\n出错线程:" + t.getName() + "\n出错信息:" + e.getLocalizedMessage());
        startActivity(intent);
        //这里必须killProcess,否则会黑屏
        android.os.Process.killProcess(android.os.Process.myPid());
    }
});
/**
 * 奔溃跳到这里
 */
public class ErrorActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_error);

        String err = getIntent().getStringExtra("err");
        //弹框提示
        new AlertDialog.Builder(this)
                .setCancelable(false)
                .setTitle("错误")
                .setMessage(err)
                .setPositiveButton("重启应用", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent intent = new Intent(Util.getContext(), MainActivity.class);
                        startActivity(intent);
                        finish();
                    }
                })
                .show();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值