setUncaughtExceptionHandler
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
1
1
1
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置该线程
由于未捕获到异常而突然终止时调用的处理程序。
通过明确设置
未捕获到的异常处理程序,线程可以完全控制它
对未捕获到的异常作出响应的方式。
如果没有设置这样的处理程序,则该线程的
ThreadGroup 对象将充当其处理程序。
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
1
1
1
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()
返回该线程由于未捕获到异常而突然终止时调用的处理程序。
如果该线程尚未明确设置未捕获到的异常处理程序,则返回该线程的 ThreadGroup 对象,除非该线程已经
终止,在这种情况下,将返回 null。
setDefaultUncaughtExceptionHandler
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
1
1
1
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
设置当线程由于未捕获到异常而突然终止,
并且没有为该线程定义其他处理程序时所调用的默认处理程序。
未捕获到的异常处理
首先由线程控制,然后由线程的
ThreadGroup 对象控制,最后由未捕获到的
默认异常处理程序控制。
如果线程不设置明确的未捕获到的异常处理程序,并且该线程的
线程组(包括父线程组)未特别指定其
uncaughtException 方法,则将调用
默认处理程序的 uncaughtException 方法。
通过设置未捕获到的默认异常处理程序,应用程序可以
为那些已经接受系统提供的任何“默认”行为的线程改变未捕获到的异常处理方式(如记录到某一特定设备或文件)。
请注意,未捕获到的默认异常处理程序通常
不应顺从该线程的 ThreadGroup 对象,因为这可能导致无限递归。
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
1
1
1
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
返回线程由于未捕获到异常而突然终止时调用的默认处理程序。如果返回值为 null,则没有默认处理程序。
Thread.UncaughtExceptionHandler
public static interface Thread.UncaughtExceptionHandler
1
1
1
public static interface Thread.UncaughtExceptionHandler
所有已知实现类:
ThreadGroup
当 Thread 因未捕获的异常而突然终止时,调用处理程序的接口。
当某一线程因未捕获的异常而即将终止时,Java 虚拟机将使用
Thread.getUncaughtExceptionHandler() 查询该线程以获得其 UncaughtExceptionHandler 的线程,并调用处理程序的 uncaughtException 方法,将
线程和异常作为参数传递。
如果某一线程没有明确设置其 UncaughtExceptionHandler,则将它的 ThreadGroup 对象作为其 UncaughtExceptionHandler。如果 ThreadGroup 对象对处理异常没有什么特殊要求,那么它可以将调用转发给默认的未捕获异常处理程序。
void uncaughtException(Thread t, Throwable e)
1
1
1
void uncaughtException(Thread t, Throwable e)
当给定线程因给定的未捕获异常而终止时,调用该方法。
Java 虚拟机将忽略该方法抛出的任何异常。
JAVA 测试案例
public class Test {
public static void main(String[] args) {
setDefaultUncaughtExceptionHandler();
test();
}
private static void test() {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("子线程异常前");
System.out.println(1 / 0);
}
}).start();
System.out.println("当前线程异常前");
System.out.println(1 / 0);
System.out.println("异常后的代码不能执行了");
}
private static void setDefaultUncaughtExceptionHandler() {
UncaughtExceptionHandler currentHandler = new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("【当前线程的Handler处理异常信息】" + t.toString() + "\n" + e.getMessage());
}
};
UncaughtExceptionHandler defaultHandler = new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
printWriter.write("start------------\n");
e.printStackTrace(printWriter);
printWriter.write("------------end");
printWriter.close();
System.out.println("【默认的Handler处理异常信息】" + writer.getBuffer().toString());
}
};
Thread.currentThread().setUncaughtExceptionHandler(currentHandler);
Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
}
}
x
42
1
public class Test {
2
public static void main(String[] args) {
3
setDefaultUncaughtExceptionHandler();
4
test();
5
}
6
7
private static void test() {
8
new Thread(new Runnable() {
9
10
public void run() {
11
System.out.println("子线程异常前");
12
System.out.println(1 / 0);
13
}
14
}).start();
15
System.out.println("当前线程异常前");
16
System.out.println(1 / 0);
17
System.out.println("异常后的代码不能执行了");
18
}
19
20
private static void setDefaultUncaughtExceptionHandler() {
21
UncaughtExceptionHandler currentHandler = new UncaughtExceptionHandler() {
22
23
public void uncaughtException(Thread t, Throwable e) {
24
System.out.println("【当前线程的Handler处理异常信息】" + t.toString() + "\n" + e.getMessage());
25
}
26
};
27
UncaughtExceptionHandler defaultHandler = new UncaughtExceptionHandler() {
28
29
public void uncaughtException(Thread t, Throwable e) {
30
StringWriter writer = new StringWriter();
31
PrintWriter printWriter = new PrintWriter(writer);
32
printWriter.write("start------------\n");
33
e.printStackTrace(printWriter);
34
printWriter.write("------------end");
35
printWriter.close();
36
System.out.println("【默认的Handler处理异常信息】" + writer.getBuffer().toString());
37
}
38
};
39
Thread.currentThread().setUncaughtExceptionHandler(currentHandler);
40
Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
41
}
42
}
运行结果
子线程异常前
当前线程异常前
【当前线程的Handler处理异常信息】Thread[main,5,main]
/ by zero
【默认的Handler处理异常信息】start------------
java.lang.ArithmeticException: / by zero
at Test$1.run(Test.java:16)
at java.lang.Thread.run(Thread.java:745)
------------end
1
子线程异常前
2
当前线程异常前
3
【当前线程的Handler处理异常信息】Thread[main,5,main]
4
/ by zero
5
【默认的Handler处理异常信息】start------------
6
java.lang.ArithmeticException: / by zero
7
at Test$1.run(Test.java:16)
8
at java.lang.Thread.run(Thread.java:745)
9
------------end
Android 中的一个实用案例
异常处理类
/**
* Desc:采集崩溃日志
*
* @author <a href="http://www.cnblogs.com/baiqiantao">白乾涛</a><p>
* @tag 崩溃日志<p>
* @date 2018/5/2 14:12 <p>
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String LOG_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crashLog/";
private Application application;
private static CrashHandler instance = new CrashHandler();
private CrashHandler() {//构造方法私有
}
public static CrashHandler getInstance() {
return instance;
}
public void init(Application application) {
this.application = application;
Thread.setDefaultUncaughtExceptionHandler(instance);//设置该CrashHandler为系统默认的
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
saveInfoToFile(collectCrashInfo(ex));//保存错误信息
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(application, "程序开小差了,将会在2秒后退出", Toast.LENGTH_SHORT).show();//使用Toast来显示异常信息
Looper.loop();
}
}.start();
SystemClock.sleep(2000);//延迟2秒杀进程
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
private String collectCrashInfo(Throwable ex) {
if (ex == null) return "";
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable throwable = ex.getCause();
while (throwable != null) {
throwable.printStackTrace(printWriter);
throwable = throwable.getCause();//逐级获取错误信息
}
String crashInfo = writer.toString();
Log.i("bqt", "【错误信息】" + crashInfo);
printWriter.close();
return crashInfo;
}
private void saveInfoToFile(String crashInfo) {
try {
File dir = new File(LOG_PATH);
if (!dir.exists()) {
dir.mkdirs();
}
String date = new SimpleDateFormat("yyyy.MM.dd_HH_mm_ss", Locale.getDefault()).format(new Date());
String fileName = LOG_PATH + "crash_" + date + ".txt";
FileWriter writer = new FileWriter(fileName);//如果保存失败,很可能是没有写SD卡权限
writer.write(crashInfo);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//如果保存失败,很可能是没有写SD卡权限
x
1
/**
2
* Desc:采集崩溃日志
3
*
4
* @author <a href="http://www.cnblogs.com/baiqiantao">白乾涛</a><p>
5
* @tag 崩溃日志<p>
6
* @date 2018/5/2 14:12 <p>
7
*/
8
public class CrashHandler implements Thread.UncaughtExceptionHandler {
9
private static final String LOG_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crashLog/";
10
private Application application;
11
12
private static CrashHandler instance = new CrashHandler();
13
14
private CrashHandler() {//构造方法私有
15
}
16
17
public static CrashHandler getInstance() {
18
return instance;
19
}
20
21
public void init(Application application) {
22
this.application = application;
23
Thread.setDefaultUncaughtExceptionHandler(instance);//设置该CrashHandler为系统默认的
24
}
25
26
27
public void uncaughtException(Thread thread, Throwable ex) {
28
saveInfoToFile(collectCrashInfo(ex));//保存错误信息
29
new Thread() {
30
31
public void run() {
32
Looper.prepare();
33
Toast.makeText(application, "程序开小差了,将会在2秒后退出", Toast.LENGTH_SHORT).show();//使用Toast来显示异常信息
34
Looper.loop();
35
}
36
}.start();
37
SystemClock.sleep(2000);//延迟2秒杀进程
38
android.os.Process.killProcess(android.os.Process.myPid());
39
System.exit(0);
40
}
41
42
private String collectCrashInfo(Throwable ex) {
43
if (ex == null) return "";
44
45
Writer writer = new StringWriter();
46
PrintWriter printWriter = new PrintWriter(writer);
47
ex.printStackTrace(printWriter);
48
Throwable throwable = ex.getCause();
49
while (throwable != null) {
50
throwable.printStackTrace(printWriter);
51
throwable = throwable.getCause();//逐级获取错误信息
52
}
53
String crashInfo = writer.toString();
54
Log.i("bqt", "【错误信息】" + crashInfo);
55
printWriter.close();
56
return crashInfo;
57
}
58
59
private void saveInfoToFile(String crashInfo) {
60
try {
61
File dir = new File(LOG_PATH);
62
if (!dir.exists()) {
63
dir.mkdirs();
64
}
65
String date = new SimpleDateFormat("yyyy.MM.dd_HH_mm_ss", Locale.getDefault()).format(new Date());
66
String fileName = LOG_PATH + "crash_" + date + ".txt";
67
FileWriter writer = new FileWriter(fileName);//如果保存失败,很可能是没有写SD卡权限
68
writer.write(crashInfo);
69
writer.close();
70
} catch (Exception e) {
71
e.printStackTrace();
72
}
73
}
74
}
获取的异常信息
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
at com.bqt.test.MainActivity.onListItemClick(MainActivity.java:34)
at android.app.ListActivity$2.onItemClick(ListActivity.java:319)
at android.widget.AdapterView.performItemClick(AdapterView.java:339)
at android.widget.AbsListView.performItemClick(AbsListView.java:1705)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:4171)
at android.widget.AbsListView$13.run(AbsListView.java:6735)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1534)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1424)
14
1
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
2
at com.bqt.test.MainActivity.onListItemClick(MainActivity.java:34)
3
at android.app.ListActivity$2.onItemClick(ListActivity.java:319)
4
at android.widget.AdapterView.performItemClick(AdapterView.java:339)
5
at android.widget.AbsListView.performItemClick(AbsListView.java:1705)
6
at android.widget.AbsListView$PerformClick.run(AbsListView.java:4171)
7
at android.widget.AbsListView$13.run(AbsListView.java:6735)
8
at android.os.Handler.handleCallback(Handler.java:751)
9
at android.os.Handler.dispatchMessage(Handler.java:95)
10
at android.os.Looper.loop(Looper.java:154)
11
at android.app.ActivityThread.main(ActivityThread.java:6682)
12
at java.lang.reflect.Method.invoke(Native Method)
13
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1534)
14
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1424)
2018-6-1