JAVA UncaughtExceptionHandler 处理

原创 2016年08月28日 22:21:49

Thread的run方法是不抛出任何检查型异常(checked exception)的,但是它自身却可能因为一个异常而被终止,导致这个线程的终结。最麻烦的是,在线程中抛出的异常即使使用try…catch也无法截获,因此可能导致一些问题出现,比如异常的时候无法回收一些系统资源,或者没有关闭当前的连接等等。
(PS:Callalble是可抛出异常)

如果需要捕获系统的未捕获异常(如系统抛出了未知错误,这种异常没有捕获,这将导致系统莫名奇妙的关闭,使得用户体验差),可以通过Thread.setUncaughtExceptionHandler(UncaughtExceptionHandler)来处理这种异常。

例子:

public class ExceptionHandler implements UncaughtExceptionHandler{

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("handle run in thread:"+Thread.currentThread().getName());

        System.out.println("thread:"+t.getName()+" throwing exception");
        e.printStackTrace();    
    }

}

public class Test implements Runnable{
    public static void main(String args[]) throws InterruptedException, FileNotFoundException, IOException, ClassNotFoundException 
    {

        Thread t=new Thread(new Test());
        t.setUncaughtExceptionHandler(new ExceptionHandler());
        t.start();
    }

输出:

run func
exception thread running:Thread-0
handle run in thread:Thread-0
thread:Thread-0 throwing exception
java.lang.RuntimeException
    at Test.fun(Test.java:43)
    at Test.run(Test.java:37)
    at java.lang.Thread.run(Unknown Source)

另外,这个例子同时也说明了异常处理函数UncaughtExceptionHandle是运行在抛出异常的线程中的。

如果是使用了线程池,那应该如何处理呢?
我们知道线程池中我们只能提交Runable,Callable对象,而不是Thread对象,代码类似与:

        ExecutorService pool=Executors.newCachedThreadPool();
        for(int i=0;i<10;i++)
        {
            Test task=new Test();
            pool.execute(task);
        }

为了能够也能设置UncaughtExceptionHandler,我们能够通过线程池的ThreadFactory,使得线程池中的线程特殊化。
代码如下:

import java.lang.Thread.UncaughtExceptionHandler;

public class ExceptionHandler implements UncaughtExceptionHandler{

    public static ExceptionHandler instance=new ExceptionHandler();

    public static ExceptionHandler getInstance()
    {
        return instance;
    }

    @Override
    synchronized public void uncaughtException(Thread t, Throwable e) {

        System.out.println("handle run in thread:"+Thread.currentThread().getName());       
        System.out.println("thread:"+t.getName()+" throwing exception");
        StackTraceElement ele[]  =e.getStackTrace();
        for(StackTraceElement s:ele)
        {
            System.out.println("\t"+s.toString());
        }

    }

}

上面的handle方法同步是为了输出信息更好辨认,并无其他特殊需求。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;


class SpecialThreadFactory implements ThreadFactory{

    @Override
    public Thread newThread(Runnable r) {
        Thread t=new Thread(r);
        t.setUncaughtExceptionHandler(ExceptionHandler.getInstance());
        return t;
    }

}


public class Test implements Runnable{
    public static void main(String args[]) throws InterruptedException, FileNotFoundException, IOException, ClassNotFoundException 
    {
        ExecutorService pool=Executors.newCachedThreadPool(new SpecialThreadFactory());
        for(int i=0;i<10;i++)
        {
            Test task=new Test();
            pool.execute(task);
        }

        pool.shutdown();
    }

    @Override
    public void run() {
        fun();  
    }
    public static void fun()
    {
        throw new RuntimeException();
    }

}

结果

handle run in thread:Thread-1
thread:Thread-1 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-3
thread:Thread-3 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-5
thread:Thread-5 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-7
thread:Thread-7 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-9
thread:Thread-9 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-0
thread:Thread-0 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-2
thread:Thread-2 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-4
thread:Thread-4 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-6
thread:Thread-6 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)
handle run in thread:Thread-8
thread:Thread-8 throwing exception
    Test.fun(Test.java:50)
    Test.run(Test.java:45)
    java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    java.lang.Thread.run(Unknown Source)

总结
1.UncaughtExceptionHandler用来处理线程未捕获异常,在发生异常的线程中运行处理代。
2.线程池中的线程通过ThreadFactory来进行UncaughtExeceptionHandle的注册。

3.突然想到一个问题:如果抛出异常的线程遇到不可恢复的异常,则还能运行handle相关代码么?

版权声明:转载 请标注 出处

JAVA多线程之UncaughtExceptionHandler——处理非正常的线程中止

当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境中,线程抛出的异常是不能用try....catch捕获的,这样就有可能导致一些问题的出现,比如异...
  • u013256816
  • u013256816
  • 2015年12月28日 11:29
  • 12860

Android Thread.UncaughtExceptionHandler捕获

在Java 的异常处理机制中: 如果抛出的是Exception异常的话,必须有try..catch..进行处理,属于checked exception。 如果抛出的是RuntimeExceptio...
  • wangbole
  • wangbole
  • 2012年11月08日 12:03
  • 17594

未处理异常处理器 UncaughtExceptionHandler 实现 崩溃日志保存 与 重启应用

前言当我们编写程序的时候 , 遇到会抛出异常的方法的时候 , 我们一般会采取 try … catch 的方式:try { bitmap = BitmapFactory.decodeSt...
  • ocwvar
  • ocwvar
  • 2016年05月26日 13:59
  • 902

使用UncaughtExceptionHandler保存全局异常

网上关于安卓开发过程中出现的异常捕抓问题已经讲得非常透彻了,现在为自己总结一下使用UncaughtExceptionHandler捕抓程序中没有处理的异常,不至于弹出: 那么这里的程序结构为: ...
  • dreamInTheWorld
  • dreamInTheWorld
  • 2015年02月09日 11:34
  • 797

【Android开发】UncaughtExceptionHandler接口详解

Android开发:UncaughtExceptionHandler接口详解
  • BrilliantEagle
  • BrilliantEagle
  • 2015年09月14日 20:49
  • 1621

手写CrashHandler实现UncaughtExceptionHandler拦截android异常

手写CrashHandler实现UncaughtExceptionHandler拦截android异常作者:码字员小D有点复杂,虽然知道原理,但是并不好从哪开始写了。。。。。。首先这是个需要在整个ap...
  • fancylovejava
  • fancylovejava
  • 2015年04月30日 16:16
  • 10785

【移动开发】捕获异常信息_UncaughtExceptionHandler

当程序崩溃(Crash)的时候,默认是不对异常信息做处理的。如果想要把异常信息保存到本地文件中,或上传的服务器。那么就要借助UncaughtExceptionHandler这个类。 首先,实例化Un...
  • manoel
  • manoel
  • 2014年09月22日 17:27
  • 4847

实现UncaughtExceptionHandler来实现获取应用全局的crash信息

Android应用不可避免的会出现各种崩溃crash,平时我们可能会通过try-catch来捕获异常,可是我们总不可能每一段代码都try-catch,所以我们还是会有很多捕获不到的异常,而且一旦应用发...
  • wozuihaole
  • wozuihaole
  • 2017年04月18日 10:48
  • 182

Android捕获异常处理——UncaughtExceptionHandler

日常代码的编写中,你遇到的程序崩溃肯定不会少。 空指针、转型失败、数组越界之类的,你应该都有碰到。当你碰到这些的时候,你代码中已经有写了try-catch,但是它并没有把这可能的异常捕获处理。 你...
  • yangzhaomuma
  • yangzhaomuma
  • 2015年12月17日 19:24
  • 827

【IOS】异常捕获 拒绝闪退 让应用从容的崩溃 UncaughtExceptionHandler

虽然大家都不愿意看到程序崩溃,但可能崩溃是每个应用必须面对的现实,既然崩溃已经发生,无法阻挡了,那我们就让它崩也崩得淡定点吧。 IOS SDK中提供了一个现成的函数 NSSetUncaughtExce...
  • yhhwatl
  • yhhwatl
  • 2014年06月25日 14:12
  • 8926
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:JAVA UncaughtExceptionHandler 处理
举报原因:
原因补充:

(最多只允许输入30个字)