在其他线程中抛出异常会导致主线程崩溃吗?

Qin*_*ing 1 java multithreading android exception-handling

我对此表示怀疑,例如,在Java类的main方法中,下面有一些代码:

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");

    }
Run Code Online (Sandbox Code Playgroud)

此IllegalStateException不会停止执行主方法,我可以看到我打印了“ xxx”。

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

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

谢谢

logcat日志:

致命异常:线程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)
Run Code Online (Sandbox Code Playgroud)

Sau*_*abh 5

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

Fron Android的文档在这里

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

未捕获的异常处理首先由线程控制,然后由线程的ThreadGroup对象控制,最后由默认的未捕获的异常处理程序控制。如果线程没有设置显式的未捕获异常处理程序,并且线程的线程组(包括父线程组)未专用于其uncaughtException方法,则将调用默认处理程序的uncaughtException方法。

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

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

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

现在,如果您进行更深入的研究,您会发现Android框架为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());
Run Code Online (Sandbox Code Playgroud)

请记住,可以通过调用特定线程来覆盖该线程的未捕获异常处理程序setUncaughtExceptionHandler。如果您在上面的示例中这样做,您将注意到该应用程序不再崩溃。