How to re-throw an exception

2019-04-04 09:00发布

In my onCreate() I set an UncaughtException handler as follows:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
       Log.e(getMethodName(2), "uncaughtException", throwable);
       android.os.Process.killProcess(android.os.Process.myPid());
    }
});

It works OK, but I would like to get back the system's default behavior of displaying the force-close dialog to the user.

If I try to replace the KillProcess() call with a throw throwable the compiler complains that I need to surround it with a try/catch.

If I surround it with a try/catch:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        try {
            Log.e(getMethodName(2), "uncaughtException", throwable);
            throw throwable;
        }
        catch (Exception e) {           
        }
        finally {               
        }
    }
});

The compiler still complains that throw throwable needs to be surrounded with a try/catch.

How do I re-throw that throwable? Such that except for that informative Log.e() the system behaves exactly as before: As is I never set a default UncaughtException handler.

4条回答
Melony?
2楼-- · 2019-04-04 09:39

first, you don't need to re-throw the exception. uncaughtException() does not consume the exception. you do however have to call through to the default uncaught exception handler's method. so something like,

class MyUEH implements UncaughtExceptionHandler {
  private static final UncaughtExceptionHandler default = Thread.getDefaultUncaughtExceptionHandler();

    public void uncaughtException(Thread t, Throwable e) {
        Log.e("Tag", "uncaughtException", throwable);
        default.uncaughtException(t, e);
    }
}

second, you don't need to kill the process yourself. the default UEH will handle that when you call through to it.

third, the default UEH will show (or cause to be shown) the standard crash (force close) dialog to the user. keep in mind that if your method hangs (because you are doing IO for example), then the user will not see the crash dialog until your method exits.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-04-04 09:42

If you set default uncaught exception handler, you are expected to consume the exception in it. That is reflected by the fact that uncaughtException does not declare any exception.

There should be no obvious reason to re-throw it. It will just be printed in log second time and thread will die anyway. If you really want that, then just wrap throwable in RuntimeException and re-throw.

查看更多
够拽才男人
4楼-- · 2019-04-04 09:48

Try:

public class CustomExceptionHandler implements UncaughtExceptionHandler {

    private UncaughtExceptionHandler defaultUEH;

    public CustomExceptionHandler() {
        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
    }

    public void uncaughtException(Thread t, Throwable e) {
        Log.e("Tag", "uncaughtException", throwable);
        defaultUEH.uncaughtException(t, e);
    }
}

and then Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

Adapted from this answer.

查看更多
该账号已被封号
5楼-- · 2019-04-04 09:53

There is no reason to rethrow the Throwable, as per the javadoc, it is simply ignored. The thread is terminating at this point, you're just setting up whatever last actions it's to attempt before exiting.

For the sake of argument, if you did want to rethrow a throwable, you'd do something like this:

public void reThrow(Throwable t) {
    if (RuntimeException.class.isAssignableFrom(t.getClass())) {
        throw (RuntimeException)t;
    } else if (Error.class.isAssignableFrom(t.getClass())) {
        throw (Error) t;
    } else {
        throw new UndeclaredThrowableException(t);
    }
}
查看更多
登录 后发表回答