异常捕获 UncaughtExceptionHandler MD

时间:2023-02-06 15:50:57
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

异常捕获

setUncaughtExceptionHandler

public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

设置该线程由于未捕获到异常而突然终止时调用的处理程序。

通过明确设置未捕获到的异常处理程序,线程可以完全控制它对未捕获到的异常作出响应的方式。

如果没有设置这样的处理程序,则该线程的 ThreadGroup 对象将充当其处理程序。

public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler()

返回该线程由于未捕获到异常而突然终止时调用的处理程序。

如果该线程尚未明确设置未捕获到的异常处理程序,则返回该线程的 ThreadGroup 对象,除非该线程已经终止,在这种情况下,将返回 null。

setDefaultUncaughtExceptionHandler

public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。

未捕获到的异常处理首先由线程控制,然后由线程的 ThreadGroup 对象控制,最后由未捕获到的默认异常处理程序控制。

如果线程不设置明确的未捕获到的异常处理程序,并且该线程的线程组(包括父线程组)未特别指定其 uncaughtException 方法,则将调用默认处理程序的 uncaughtException 方法。

通过设置未捕获到的默认异常处理程序,应用程序可以为那些已经接受系统提供的任何“默认”行为的线程改变未捕获到的异常处理方式(如记录到某一特定设备或文件)。

请注意,未捕获到的默认异常处理程序通常不应顺从该线程的 ThreadGroup 对象,因为这可能导致无限递归。

public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()

返回线程由于未捕获到异常而突然终止时调用的默认处理程序。如果返回值为 null,则没有默认处理程序。

Thread.UncaughtExceptionHandler

public static interface Thread.UncaughtExceptionHandler

所有已知实现类:ThreadGroup

当 Thread 因未捕获的异常而突然终止时,调用处理程序的接口。

当某一线程因未捕获的异常而即将终止时,Java 虚拟机将使用 Thread.getUncaughtExceptionHandler() 查询该线程以获得其 UncaughtExceptionHandler 的线程,并调用处理程序的 uncaughtException 方法,将线程和异常作为参数传递。

如果某一线程没有明确设置其 UncaughtExceptionHandler,则将它的 ThreadGroup 对象作为其 UncaughtExceptionHandler。如果 ThreadGroup 对象对处理异常没有什么特殊要求,那么它可以将调用转发给默认的未捕获异常处理程序。

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);
}
}

运行结果

子线程异常前
当前线程异常前
【当前线程的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

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();
}
}
}

获取的异常信息

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)

2018-6-1