将在另一个线程中抛出的异常会使主线程崩溃吗?

时间:2016-12-01 03:20:36

标签: java android multithreading exception-handling

我对此有疑问,例如,在Java类的主要方法中,我有以下代码:

public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                throw new IllegalStateException("sss");
            }
        }).start();


        try {
            Thread.sleep(2000);
        } catch (Exception e) {

        }

        System.out.println("xxx");

    }

这个IllegalStateException不会阻止主方法执行,我可以看到我打印“xxx”。

然而,在Android开发中,如果我在Activity的oncreate()方法中执行相同操作,则会使App崩溃。

我想知道Android如何处理这个以及为什么它会使应用程序崩溃。

由于

logcat日志:

致命异常:Thread-248

                                                        Process: com.abc.android, PID: 3673
                                                        java.lang.IllegalStateException: sss
                                                            at com.abc.android.MainActivity$1.run(MainActivity.java:80)
                                                            at java.lang.Thread.run(Thread.java:818)

1 个答案:

答案 0 :(得分:4)

每个线程都有一个选项来设置一个未被捕获的处理程序,当线程遇到异常时将调用该处理程序

Fron Android&here上的文档:

  

void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh):   设置当线程由于未捕获的异常而突然终止时调用的默认处理程序,并且没有为该线程定义其他处理程序。

     

未捕获的异常处理首先由线程控制,然后由线程的ThreadGroup对象控制,最后由默认的未捕获异常处理程序控制。如果线程没有明确的未捕获异常处理程序集,并且线程的线程组(包括父线程组)没有专门化其uncaughtException方法,则将调用默认处理程序的uncaughtException方法。 / p>      

通过设置默认的未捕获异常处理程序,应用程序可以更改已经接受任何"默认&#34的线程处理未捕获异常的方式(例如,记录到特定设备或文件) ;系统提供的行为。

     

请注意,默认的未捕获异常处理程序通常不应该遵循线程的ThreadGroup对象,因为这可能会导致无限递归。

另请注意,setDefaultUncaughtExceptionHandler是一种静态方法,这意味着它将应用于应用程序创建的所有线程。

现在,如果你深入挖掘,你会发现Android Framework为RuntimeInit.java中的所有线程定义了一个默认的未捕获异常处理程序,它继续报告崩溃并终止进程。

/**
 * Use this to log a message when a thread exits due to an uncaught
 * exception.  The framework catches these for the main threads, so
 * this should only matter for threads created by applications.
 */
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
    public void uncaughtException(Thread t, Throwable e) {
        try {
            // Don't re-enter -- avoid infinite loops if crash-reporting crashes.
            if (mCrashing) return;
            mCrashing = true;
            if (mApplicationObject == null) {
                Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
            } else {
                Slog.e(TAG, "FATAL EXCEPTION: " + t.getName(), e);
            }
            // Bring up crash dialog, wait for it to be dismissed
            ActivityManagerNative.getDefault().handleApplicationCrash(
                    mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
        } catch (Throwable t2) {
            try {
                Slog.e(TAG, "Error reporting crash", t2);
            } catch (Throwable t3) {
                // Even Slog.e() fails!  Oh well.
            }
        } finally {
            // Try everything to make sure this process goes away.
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
    }
}
private static final void commonInit() {
    if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
    /* set default handler; this applies to all threads in the VM */
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

请记住,您可以通过调用该线程的setUncaughtExceptionHandler覆盖特定线程的未捕获异常处理程序。如果您在上面的示例中执行此操作,您会发现应用程序不再崩溃。