Directory to summarize

  • There are several common apis for exception handling
  • 01.UncaughtExceptionHandler
  • 02.Java thread processing exception analysis
  • 03.Android thread processing exception analysis
  • Using setDefaultUncaughtExceptionHandler 04. Why

At the forefront of

  • The last article introduced the crash library crash restart, crash record record, view and share logs and other functions.
  • Project address: github.com/yangchong21…
  • Welcome to star

There are several common apis for exception handling

  • setUncaughtExceptionHandler
    • public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
      • Sets the handler that is called when the thread terminates abruptly because an exception was not caught.
      • By explicitly setting uncaught exception handlers, a thread has full control over how it responds to uncaught exceptions.
      • If no such handler is set, the thread’s ThreadGroup object acts as its handler.
    • public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
      • Returns the handler that is called when the thread terminates abruptly because it did not catch an exception.
      • If the thread has not explicitly set an uncaught exception handler, the ThreadGroup object for that thread is returned, unless the thread has terminated, in which case NULL is returned.
  • setDefaultUncaughtExceptionHandler
    • public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
      • Sets the default handler to be called when a thread terminates abruptly because an exception was not caught and no other handlers are defined for that thread.
      • Uncaught exception handling is controlled first by the thread, then by the thread’s ThreadGroup object, and finally by the uncaught default exception handler.
      • If a thread does not set an explicit uncaughtException handler and the thread group (including the parent thread group) does not specifically specify its uncaughtException method, the uncaughtException method of the default handler is called.

      By setting a default exception handler that is not caught, an application can change the handling of an uncaught exception (such as logging to a particular device or file) for threads that have accepted any “default” behavior provided by the system.

    • public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
      • Returns the default handler that is called when the thread terminates abruptly because an exception was not caught.
      • If the return value is NULL, there is no default handler.
  • Thread.UncaughtExceptionHandler
    • public static interface Thread.UncaughtExceptionHandler
      • All known implementation classes: ThreadGroups
      • The handler’s interface is called when Thread terminates abruptly due to an uncaught exception.
      • When a Thread is terminated due to an uncaught exception, the Java virtual machine will use the Thread, getUncaughtExceptionHandler () query this Thread to get its UncaughtExceptionHandler threads, And calls the handler’s uncaughtException method, passing the thread and exception as arguments.
      • If a thread does not explicitly set its UncaughtExceptionHandler, its ThreadGroup object is treated as its UncaughtExceptionHandler.
      • If a ThreadGroup object has no special requirements for handling exceptions, it can forward the call to the default uncaught exception handler.

01.UncaughtExceptionHandler

  • The official introduction is:
    • Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception.
    • When a thread is about to terminate due to an uncaught exception the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using getUncaughtExceptionHandler() and will invoke the handler’s uncaughtException method, passing the thread and the exception as arguments. If a thread has not had its UncaughtExceptionHandler explicitly set, then its ThreadGroup object acts as its UncaughtExceptionHandler. If the ThreadGroup object has no special requirements for dealing with the exception, it can forward the invocation to the default uncaught exception handler.
  • The general meaning after translation is
    • The UncaughtExceptionHandler interface is used to handle the sudden termination of a thread due to an uncaught exception.
    • When a thread is about to terminate due to an uncaught exception, Java virtual machine will by calling getUncaughtExceptionHandler () function to query the thread UncaughtExceptionHandler and invoke the processor The uncaughtException method passes thread and exception information as arguments. If a thread does not explicitly set an UncaughtExceptionHandler, the ThreadGroup object will do this instead of UncaughtExceptionHandler. If a ThreadGroup is not explicitly specified to handle the exception, the ThreadGroup is forwarded to the default handler for uncaught exceptions.
  • Exception callback: uncaughtException
    • UncaughtException (Thread t, Throwable e) is an abstract method through which Thread objects and exception objects are passed in when a given Thread terminates due to an uncaughtException.
  • Set the default uncaught exception handler: setDefaultUncaughtExceptionHandler
    • void setDefaultUncaughtExceptionHandler (Thread.UncaughtExceptionHandler eh)
    • Set a handler to be called automatically when a thread terminates suddenly due to an uncaught exception.
    • Control of uncaught exception handling is first handled by the current thread, and if the thread does not catch and handle the exception, it is handled by the thread’s ThreadGroup object, and finally by the default uncaught exception handler.
    • By setting the default uncaught exception handler, an application can change the way uncaught exceptions are handled, such as logging to a specified device or file, for threads that already have a default uncaught exception handler provided by the system.
  • The handler will report thread terminations and unexplained exceptions. If there is no custom handler, the thread management group will default to the handler that reports the exception.
    • The ThreadHandler class implements the UncaughtExceptionHandler interface. The pseudocode is shown below
    public class ThreadHandler implements Thread.UncaughtExceptionHandler {
    
        private Thread.UncaughtExceptionHandler mDefaultHandler;
        private boolean isInit = false;
        /** * CrashHandler instance */
        private static ThreadHandler INSTANCE;
    
        /** * Get CrashHandler instance, singleton mode */
        public static ThreadHandler getInstance(a) {
            if (INSTANCE == null) {
                synchronized (CrashHandler.class) {
                    if (INSTANCE == null) {
                        INSTANCE = newThreadHandler(); }}}return INSTANCE;
        }
    
        /** * this function is called when UncaughtException occurs */
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            if(mDefaultHandler ! =null) {
                // After collecting the information, the system handles the crash itself
                UncaughtException (Thread t, Throwable e) is an abstract method
                This method is used to pass in thread objects and exception objects when a given thread terminates due to an uncaught exception.
                mDefaultHandler.uncaughtException(t, e);
            } else {
                // Otherwise handle it yourself}}/** * Register the Context object, get the default UncaughtException handler, and set the CrashHandler to the default handler@param ctx
         */
        public void init(Application ctx) {
            if (isInit){
                return;
            }
            // Get the system default UncaughtExceptionHandler
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            // Set the current instance as the system default exception handler
            // Set a handler that will be called automatically when a thread terminates suddenly due to an uncaught exception.
            // Control of uncaught exception handling is handled first by the current thread. If the thread does not catch and handle the exception, it is handled by the thread's ThreadGroup object, and finally by the default uncaught exception handler.
            Thread.setDefaultUncaughtExceptionHandler(this);
            isInit = true; }}Copy the code

02.Java thread processing exception analysis

  • Thread uncaught exception occurs, the JVM will call dispatchUncaughtException method in the Thread of the exception is passed to the Thread uncaught exception handler.
    public final void dispatchUncaughtException(Throwable e) {
        Thread.UncaughtExceptionHandler initialUeh = Thread.getUncaughtExceptionPreHandler();
        if(initialUeh ! =null) {
            try {
                initialUeh.uncaughtException(this, e);
            } catch (RuntimeException | Error ignored) {
                // Throwables thrown by the initial handler are ignored
            }
        }
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }
    
    public static UncaughtExceptionHandler getUncaughtExceptionPreHandler(a) {
        return uncaughtExceptionPreHandler;
    }
    Copy the code
  • Two uncaughtExceptionHandlers exist in the Thread. One is the static defaultUncaughtExceptionHandler, another is a static uncaughtExceptionHandler.
    // null unless explicitly set
    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
    
    // null unless explicitly set
    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
    Copy the code
    • DefaultUncaughtExceptionHandler: set a static default UncaughtExceptionHandler. Exceptions from all threads will pass by if thrown and not caught. Process fork set is the static defaultUncaughtExceptionHandler, jurisdiction for the whole process.
    • UncaughtExceptionHandler: set a for a single thread thread own uncaughtExceptionHandler, scope is small.
  • What if uncaughtExceptionHandler is not set?
    • If uncaughtExceptionHandler is not set, the uncaught exception is handled using the thread group of the thread.
    • The ThreadGroup ThreadGroup implements UncaughtExceptionHandler, so it can be used to handle uncaught exceptions. ThreadGroup class definition:
    private ThreadGroup group;
    / / ThreadGroup class is to integrate the Thread can be found. The UncaughtExceptionHandler interface
    class ThreadGroup implements Thread.UncaughtExceptionHandler{}
    Copy the code
  • ThreadGroup implements uncaughtException(Thread t, Throwable e)
    • By default, the logic for thread groups to handle uncaught exceptions is to first notify the parent thread group of the exception message,
    • Then try to use a default defaultUncaughtExceptionHandler to handle exceptions,
    • Error messages are printed to system. err if there is no default exception handler.
    • That is, the JVM provides us with a specific uncaught exception handler to set for each thread, as well as a way to set the default exception handler.
    public void uncaughtException(Thread t, Throwable e) {
        if(parent ! =null) {
            parent.uncaughtException(t, e);
        } else {
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if(ueh ! =null) {
                ueh.uncaughtException(t, e);
            } else if(! (einstanceof ThreadDeath)) {
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" "); e.printStackTrace(System.err); }}}Copy the code

03.Android thread processing exception analysis

  • In Android, when an application forks, an unintercepted exception handler is set up for the virtual machine. That is, if any thread throws an unintercepted exception while the application is running, the exception is eventually thrown to the unintercepted exception handler.
    • Find the RuntimeInit class and then the KillApplicationHandler class. First look at the main entrance of the method – > commonInit () – >, and then go down, and find setDefaultUncaughtExceptionHandler code as shown below
    • If the report crashes, do not enter again — avoid an infinite loop. If the ActivityThread profiler runs at this point, we kill the process and the buffer in memory is lost. And open the crash dialog box
    • Finally, the app is killed using the process-killing method in finally
    Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
    
    private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
        private final LoggingHandler mLoggingHandler;
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            try {
                if (mCrashing) return;
                mCrashing = true;
                if(ActivityThread.currentActivityThread() ! =null) {
                    ActivityThread.currentActivityThread().stopProfiling();
                }
                // Bring up crash dialog, wait for it to be dismissed
                ActivityManager.getService().handleApplicationCrash(
                        mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
            } catch (Throwable t2) {
                if (t2 instanceof DeadObjectException) {
                    // System process is dead; ignore
                } else {
                    try {
                        Clog_e(TAG, "Error reporting crash", t2);
                    } catch (Throwable t3) {
                        // Even Clog_e() fails! Oh well.}}}finally {
                // Try everything to make sure this process goes away.
                Process.killProcess(Process.myPid());
                System.exit(10); }}}Copy the code
  • UncaughtExceptionHandler exists in threads. When an exception occurs and is not caught. The exception is thrown by UncaughtExceptionHandler. And the thread will die. So neutron thread death is allowed on Android. ANR occurs when the main thread dies.
  • In fact, when the app process is forked out, the system has set an exception handling for the app, and the final crash will directly cause the finallly method of the handler to kill the app and exit the app directly. If you want to deal with, you can realize Thread. UncaughtExceptionHandler.

Using setDefaultUncaughtExceptionHandler 04. Why

  • Thread. UncaughtExceptionHandler interface code as shown below
    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        void uncaughtException(Thread t, Throwable e);
    }
    Copy the code
    • UncaughtExceptionHandler UncaughtExceptionHandler interface, when a thread is about to crash due to an uncaught exception, The JVM will through getUncaughtExceptionHandler () method to get the thread UncaughtExceptionHandler, this thread and abnormal as a parameter to the uncaughtException () method.
    • If a thread’s UncaughtExceptionHandler is not explicitly set, its ThreadGroup object will be treated as UncaughtExceptionHandler.
    • If the ThreadGroup exception handling objects have no special requirements, it can adjust getDefaultUncaughtExceptionHandler () method to obtain the default UncaughtExceptionHandler to handle exceptions.
  • Will UncaughtExceptionHandler be created for each thread?
    • Applications typically create many threads, and it would be too cumbersome to set UncaughtExceptionHandler for each thread.
    • Since eventually after the JVM tuning getDefaultUncaughtExceptionHandler abnormal unprocessed (), so we can set a default application startup uncaught exception handler. The calling Thread. SetDefaultUncaughtExceptionHandler (handler)
  • SetDefaultUncaughtExceptionHandler be invoked many times how to understand?
    • Thread. SetDefaultUncaughtExceptionHandler (handler) method, if be called multiple times in the last time the handler shall prevail, so if you measure the module, with the third party may be failure. In this case, before setting default hander, can pass getDefaultUncaughtExceptionHandler hander () method to obtain and keep the old, UncaughtException = uncaughtException = uncaughtException = uncaughtException = uncaughtException

Project Address:Github.com/yangchong21…