不同线程中抛出的异常会导致主线程崩溃吗?

4

我有一个疑问,例如,在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 不会阻止主方法执行,我可以看到 i 的值打印出来了。

然而,在 Android 开发中,如果我在 Activity 的 oncreate() 方法中做同样的事情,它会导致应用程序崩溃。

我想知道 Android 是如何处理这个问题的,以及为什么会导致应用程序崩溃。

谢谢。

logcat 日志:

FATAL EXCEPTION: 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)

你能发布一下你的Activity的onCreate()代码吗? - sasikumar
线程 t = new Thread(new Runnable() { @Override public void run() { throw new IllegalStateException("sss"); } }); t.start(); - Qing
你有放入布局代码吗? - sasikumar
是的,在我设置了setContentView之后,我运行了这个线程。 - Qing
你能否发布你的Logcat日志? - sasikumar
1个回答

10
每个线程都有一个选项来设置未捕获的处理程序,当线程遇到异常时将调用该处理程序。
从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());

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接