Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override handleUncaughtException without changing its functionallity

I asked this question some time back on Stackoverflow, the answer worked for me, It overrides thehandleUncaughtException, I save the exception and throws the default Unfortunately app has stopped working, but when i integrated this in my app, I am facing an issue.

This is the answer i got.

private Thread.UncaughtExceptionHandler defaultExceptionHandler;

    public void registerCrash(){
        defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
            @Override
            public void uncaughtException (Thread thread, Throwable e){
                handleUncaughtException (thread, e);
                if(defaultExceptionHandler != null){
                    defaultExceptionHandler.uncaughtException(thread, e);
                }
            }
        });
    } 

What it does, first it goes to handleUncaughtException (thread, e); i save the crash log in this method, then it reads this line

 if(defaultExceptionHandler != null){
    defaultExceptionHandler.uncaughtException(thread, e);
}

here we throw uncaught exception again, so it goes to the first line again, and again saves the exception, and this goes in loop, and application becomes not responding.

What i want is to save crash log, and then show the default Unfortunate message to user.

EDIT

On Application launch it reads this;

defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

When application crashes, it reads these lines

Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
    @Override
    public void uncaughtException (Thread thread, Throwable e){

        handleUncaughtException (thread, e); //Custom Method 

        if(defaultExceptionHandler != null){
            defaultExceptionHandler.uncaughtException(thread, e);
        }
    }

So it first goes to handleUncaughtException() there i have provided custom implementation, then it goes to this;

if(defaultExceptionHandler != null){
  defaultExceptionHandler.uncaughtException(thread, e);
}

The defaultExceptionHandler is never null; So it goes in a loop in case of multiple crashes.

I have tried adding count there, but it was 0 each time.

like image 592
dev90 Avatar asked Jul 30 '17 16:07

dev90


People also ask

How do you handle exceptions without try and catch?

throws: The throws keyword is used for exception handling without try & catch block.

How do you handle uncaught exception in Java?

The try-catch is the simplest method of handling exceptions. Put the code you want to run in the try block, and any Java exceptions that the code throws are caught by one or more catch blocks. This method will catch any type of Java exceptions that get thrown. This is the simplest mechanism for handling exceptions.


1 Answers

The most likely explanation is that your registerCrash() method is being called twice.

The first time, you register Handler 1; there is no default handler at this point, so it sets defaultExceptionHandler to null. The second time, you register Handler 2, and then update defaultExceptionHandler to point to Handler 1.

On an uncaught exception, Handler 2 gets invoked first. It calls your custom handler method, then invokes defaultExceptionHandler, which now points to Handler 1.

Handler 1 gets invoked. It calls your custom handler method a second time, then it invokes defaultExceptionHandler, which now points to itself. This step repeats until your stack overflows.

I suggest two changes. First, add a guard to ensure you only register your crash handler once. Second, don't store the fallback handler in a field; capture it in a closure so the value seen by your handler never changes.

private static final AtomicBoolean CRASH_HANDLER_REGISTERED = new AtomicBoolean();

public void registerCrash() {
    if (CRASH_HANDLER_REGISTERED.compareAndSet(false, true)) {
        final Thread.UncaughtExceptionHandler defaultHandler =
            Thread.getDefaultUncaughtExceptionHandler();

        Thread.setDefaultUncaughtExceptionHandler(
            new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread thread, Throwable e) {
                    handleUncaughtException(thread, e); // Custom Method

                    if (defaultHandler != null) {
                        defaultHandler.uncaughtException(thread, e);
                    }
                }
            }
        );
    }
}
like image 168
Mike Strobel Avatar answered Oct 16 '22 16:10

Mike Strobel