现在的位置: 首页 > 综合 > 正文

Thread.UncaughtException接口

2013年10月26日 ⁄ 综合 ⁄ 共 3795字 ⁄ 字号 评论关闭
import java.lang.Thread.UncaughtExceptionHandler;

/**
 * Thread.UncaughtExceptionHandler的用法
 */
class CrashHandler implements UncaughtExceptionHandler {
	public CrashHandler() {

	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println("系统崩溃了");
	}

}

public class UncaughtExceptionHandlerDemon {
	public static void main(String[] args) {
		Thread.currentThread().setUncaughtExceptionHandler(new CrashHandler());
		if (args != null)
			throw new NullPointerException("你妈");
		System.out.println("======");
	}
}
 

运行结果:系统崩溃了


import java.lang.Thread.UncaughtExceptionHandler;

/**
 * Thread.UncaughtExceptionHandler的用法
 */
class CrashHandler implements UncaughtExceptionHandler {
	public CrashHandler() {

	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		System.out.println("系统崩溃了");
	}

}

public class UncaughtExceptionHandlerDemon {
	public static void main(String[] args) {
		Thread.setDefaultUncaughtExceptionHandler(new CrashHandler());
		if (args != null)
			throw new NullPointerException("你妈");
		System.out.println("======");
	}
}

 

运行结果:系统崩溃了

这两者的区别是什么呢??

Thread.UncaughtExceptionHandler的API解释:

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 itsUncaughtExceptionHandler usinggetUncaughtExceptionHandler and will
invoke the handler'suncaughtException method, passing the thread and the exception as arguments. If a thread has not had itsUncaughtExceptionHandler explicitly set, then itsThreadGroup object acts as itsUncaughtExceptionHandler.
If theThreadGroup object has no special requirements for dealing with the exception, it can forward the invocation to thedefault uncaught exception handler.

简单翻译一下,不好的地方请大家指教:

  一个处理接口,当一个线程因为没有捕捉的异常导致的突然终止时,该接口被唤醒。

 当一个线程因为不能捕捉的异常将要终止的时候,JVM会调用getUncaughtExceptionHandler方法查找扎个线程对应的指定UncaughtExceptionHandler对象,并且回调这个对象的uncaughtException方法。如果这个线程没有指定的UncaughtExceptionHandler对象,那么将ThreadGroup对象作为UncaughtExceptionHandler对象,因为ThreadGroup类实现了Thread.UncaughtExceptionHandler接口;会调用顶层ThreadGroup的那个默认的UncaughtExceptionHandler对象的uncaughtException方法。

这个过程对应的源代码:

1、当发生异常的时候,比如调用 throw  new  Exception()没有捕获,进入产生异常的线程(Thread类)的dispatchUncaughtException方法

 /**
     * Dispatch an uncaught exception to the handler. This method is 
     * intended to be called only by the JVM.
     */
    private void dispatchUncaughtException(Throwable e) {
        getUncaughtExceptionHandler().uncaughtException(this, e);
    }

2、getUncaughtExceptionHandler方法如下:

 public UncaughtExceptionHandler getUncaughtExceptionHandler() { 
        return uncaughtExceptionHandler != null ?
            uncaughtExceptionHandler : group;
    }

其中uncaughtExceptionHandler是UncaughtExceptionHandler的对象,而group是ThreadGroup的对象。

3、如果我们通过public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)方法来设置指定的

UncaughtExceptionHandler对象,就直接调用这个的UncaughtExceptionHandler的uncaughtException方法,JVM退出。

4、如果我们没有通过public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)方法来设置指定的

UncaughtExceptionHandler对象,因为只是唯一的设置方式,在Thread类里面也没有给它赋值,所以为空,那么调用group的uncaughtException方法,因为ThreadGroup实现了UncaughtExceptionHandler接口

 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 (!(e instanceof ThreadDeath)) {
		System.err.print("Exception in thread \""
				 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }

这是ThreadGroup类中的code,其中parent是ThreadGroup的对象,也就是说ThreadGroup中还可以有ThreadGroup对象,

程序会先找到顶层的ThreadGroup对象。直接进入else分支,如果设置了默认的UncaughtExceptionHandler对象,那么调用默认的UncaughtExceptionHandler对象的uncaughtException方法,JVM退出。如果没有设置默认的UncaughtExceptionHandler对象,那么就打印出异常信息,最后虚拟机会退出。

这里调用的优先级是:指定的UncaughtExceptionHandler-----》ThreadGroup的默认的UncaughtExceptionHandler

注意:我们将产生的异常对象提交给了运行时环境,这个过程叫抛出异常,运行时环境将寻找对应的catch块,找到了合适的catch块,就将这个异常对象提交给catch块,这个过程叫捕捉异常,如果没有找到合适的catch块,那么运行时环境将异常对象提交给JVM,JVM得到这个异常对象后,找到产生异常的线程对应的UncaughtExceptionHandler对象,回调uncaughtException方法,然后JVM退出。

抱歉!评论已关闭.