Thread.UncaughtExceptionHandler

2023-11-18

1. 自定义Application继承Application 在清单文件中将默认的Application的android:name=“”替换成自定义的Application对象名称即可
在Oncreate中写入要实现的内容

2.
在编写APK程序时,通常会导致程序崩溃的异常,在通常情况下这些异常不能被捕获到,利用Thread.UncaughtExceptionHandler就可以捕获到这些异常。从名字就可以看出来UncaughtExceptionHandler是针对某个线程而言的,同时Thread提供了3个相关的方法:

1. void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) //为一个线程设置一个Handler
2. Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() //获取该线程的handler

3. static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)


//为一个线程设置一个默认的Handler,在程序不能捕获而退出,并且么有其他的handler时被调用

所以只要通过set方法,为一个线程设置一个handler就可以在程序异常退出时,捕获改异常,Demo1:


Thread thread = new thread(new Runnable(){
public void run() {
//Do something can throw runtime exception.
}
});
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
@Override
public void uncaughtException(Thread thread, Throwable ex) {
//TODO
System.out.println(ex.getLocalizedMessage());
});

线程的运行时异常就会被捕获,你就可以对捕获到异常进行处理


但是,由于在android编程中,大量使用线程,如果统一处理呢?因为主线程只有一个,我们可以在主线程里处理。
我们可以在主activity启动时的oncreate方法里面添加下面代码

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable ex) {
//TODO
System.out.println(ex.getLocalizedMessage());
finish();
}
});

这样就可以捕获大部分的运行时异常了

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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

JDK5.0之前,不能为单独的Thread设置UncaughtExceptionHandler,也不能指定一个默认的UncaughtExceptionHandler。为了可以设置一个UncaughtExceptionHandler,需要去继承ThreadGroup并覆写uncaughtException方法。

在JDK5.0中,我们通过Thread的实例方法setUncaughtExceptionHandler,可以为任何一个Thread设置一个UncaughtExceptionHandler。当然你也可以为所有Thread设置一个默认的UncaughtExceptionHandler,通过调用Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法,这是Thread的一个static方法。

定义一个Handler类必须实现Thread.UncaughtExceptionHandler接口的void uncaughtException(Thread t, Throwable e)方法。如果不设置一个Handler,那么单个Thread的Handler是null。但是,如果这个单个线程是ThreadGroup中的一个Thread,那么这个线程将使用ThreadGroup的UncaughtExceptionHandler。ThreadGroup自身已经实现了Thread.UncaughtExceptionHandler接口。

這樣就夠了


uncaughtException(Thread a, Throwable e)可以拿到Thread,所以在uncaughtException释放相关资源是最好的办法。

总之,JDK5.0中Thread及其相关的辅助功能得到了加强,为我们提供了很多便利和安全的解决方案:)


import java.lang.Thread.UncaughtExceptionHandler;

public class
ThreadTest {

 
public static void
main(String[] args) {
    ErrHandler handle
= null
;
    ThreadA a
= null
;

    a
= new
ThreadA();
    handle
= new
ErrHandler();
    a.setUncaughtExceptionHandler(handle);
// 加入定义的ErrHandler

    a.start();

  }

}

/**

* 自定义的一个UncaughtExceptionHandler
*/
class ErrHandler implements UncaughtExceptionHandler {
 
/**

   * 这里可以做任何针对异常的处理,比如记录日志等等
  
*/
 
public void uncaughtException(Thread a, Throwable e) {
    System.out.println(
"This is:" + a.getName() + ",Message:"

       
+ e.getMessage());
    e.printStackTrace();
  }
}

/**

* 拥有UncaughtExceptionHandler的线程
*/
class ThreadA extends Thread {

 
public
ThreadA() {

  }

 
public void
run() {

   
double i = 12 / 0;// 抛出异常的地方

  }

}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

在Java 的异常处理机制中:
如果抛出的是Exception异常的话,必须有try..catch..进行处理,属于checked exception。
如果抛出的是RuntimeException异常的话,则不是必须进行try..catch..异常处理,发生异常之后将由JVM进行处理,属于unchecked exception。
注意:为了保证程序的健壮性,建议抛出RunntimeException异常,也使用try..catch..进行处理。

这两者最本质的区别在于设计者认为使用者是否能够并且应该处理这个异常。

Java 异常的分类:
基类为:Throwable
Error 和 Exception 继承于Throwable
RuntimeException和IOException等继承Exception
其中,Error和RuntimeException及其子类属于unchecked exception, 而其他异常为checked exception。


Error类描述了Java运行系统中的内部错误以及资源耗尽的情形,应用程序不应该抛出这种类型的对象(一般是由Java虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以,在我们在程序设计时,应该更关注Exception体系。

RuntimeExcption体系,包括错误的类型转换,数组越界访问和试图访问空指针等等。如果出现RuntimeException,那么一定是你自己的错误。

其他非RuntimeExcetpion(IOException等等),这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。

在Android开发中,常常会出现uncheched Exception 导致程序的crash,为了提供良好的用户体验,并对出错的信息进行收集,以便对程序进行改进,提高程序的健壮性。因此,常使用Thread.UncaughtExceptionHandler来进行处理。

首先需要继承Thread.UncaughtExceptionHandler类

  1. public class CrashHandler implements Thread.UncaughtExceptionHandler { 
  2.     public static final String TAG = CrashHandler.class.getSimpleName(); 
  3.     private static CrashHandler INSTANCE = new CrashHandler(); 
  4.     private Context mContext; 
  5.     private Thread.UncaughtExceptionHandler mDefaultHandler; 
  6.  
  7.  
  8.     private CrashHandler() { 
  9.     } 
  10.  
  11.  
  12.     public static CrashHandler getInstance() { 
  13.         return INSTANCE; 
  14.     } 
  15.  
  16.  
  17.     public void init(Context ctx) { 
  18.         mContext = ctx; 
  19.         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 
  20.         Thread.setDefaultUncaughtExceptionHandler(this); 
  21.     } 
  22.  
  23.  
  24.     @Override 
  25.     public void uncaughtException(Thread thread, Throwable ex) { 
  26.         // if (!handleException(ex) && mDefaultHandler != null) { 
  27.         // mDefaultHandler.uncaughtException(thread, ex); 
  28.         // } else { 
  29.         // android.os.Process.killProcess(android.os.Process.myPid()); 
  30.         // System.exit(10); 
  31.         // } 
  32.         System.out.println("uncaughtException"); 
  33.  
  34.  
  35.         new Thread() { 
  36.             @Override 
  37.             public void run() { 
  38.                 Looper.prepare(); 
  39.                 new AlertDialog.Builder(mContext).setTitle("提示").setCancelable(false
  40.                         .setMessage("程序崩溃了...").setNeutralButton("我知道了", new OnClickListener() { 
  41.                             @Override 
  42.                             public void onClick(DialogInterface dialog, int which) { 
  43.                                 System.exit(0); 
  44.                             } 
  45.                         }) 
  46.                         .create().show(); 
  47.                 Looper.loop(); 
  48.             } 
  49.         }.start(); 
  50.     } 
  51.  
  52.  
  53.     /**
  54.      * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
  55.      *
  56.      * @param ex
  57.      * @return true:如果处理了该异常信息;否则返回false
  58.      */ 
  59.     private boolean handleException(Throwable ex) { 
  60.         if (ex == null) { 
  61.             return true
  62.         } 
  63.         // new Handler(Looper.getMainLooper()).post(new Runnable() { 
  64.         // @Override 
  65.         // public void run() { 
  66.         // new AlertDialog.Builder(mContext).setTitle("提示") 
  67.         // .setMessage("程序崩溃了...").setNeutralButton("我知道了", null) 
  68.         // .create().show(); 
  69.         // } 
  70.         // }); 
  71.  
  72.  
  73.         return true
  74.     } 
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    public static final String TAG = CrashHandler.class.getSimpleName();
    private static CrashHandler INSTANCE = new CrashHandler();
    private Context mContext;
    private Thread.UncaughtExceptionHandler mDefaultHandler;


    private CrashHandler() {
    }


    public static CrashHandler getInstance() {
        return INSTANCE;
    }


    public void init(Context ctx) {
        mContext = ctx;
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        // if (!handleException(ex) && mDefaultHandler != null) {
        // mDefaultHandler.uncaughtException(thread, ex);
        // } else {
        // android.os.Process.killProcess(android.os.Process.myPid());
        // System.exit(10);
        // }
        System.out.println("uncaughtException");


        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                new AlertDialog.Builder(mContext).setTitle("提示").setCancelable(false)
                        .setMessage("程序崩溃了...").setNeutralButton("我知道了", new OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                System.exit(0);
                            }
                        })
                        .create().show();
                Looper.loop();
            }
        }.start();
    }


    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
     * 
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return true;
        }
        // new Handler(Looper.getMainLooper()).post(new Runnable() {
        // @Override
        // public void run() {
        // new AlertDialog.Builder(mContext).setTitle("提示")
        // .setMessage("程序崩溃了...").setNeutralButton("我知道了", null)
        // .create().show();
        // }
        // });


        return true;
    }
}


然后在Application类中进行注册

  1. public class MyApplication extends Application{ 
  2.  
  3.  
  4.     @Override 
  5.     public void onCreate(){ 
  6.     super.onCreate(); 
  7.         initErrorHandler(); 
  8.     } 
  9.  
  10.  
  11.    private void initErrorHandler(){ 
  12.     CrashHandler handler = CrashHandler.getInstance(); 
  13.     handler.init(this); 
  14.    } 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Thread.UncaughtExceptionHandler 的相关文章

  • 如何在日期选择器中设置不在当前月份的单元格的样式

    我目前正在为我的 JavaFX 应用程序制作注册表 问题是 当日期选择器中的单元格不在页面的月份上时 我想让该单元格变灰 让我们看看我当前的日期选择器 我的日期选择器 正如您所看到的 我希望下个月的日期 27 日 28 日 30 日以及 1
  • 热重载在docker中运行的java程序

    我开发了一个java程序 应该在docker中运行 然而 我在调试docker中运行的java程序时遇到了很多痛苦 我在网上搜索 一些教程提出了像 spring dev tools 这样的工具 因为我的java程序是基于spring boo
  • 我需要在 Spring 中检查每个控制器中的有效会话吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设在 Spring Mvc 的 Web 应用程序中 我们是否需要检查每个控制器或 jsps 中的有效会话 我该如何解决 MVC 中的
  • Java程序中的数组奇怪的行为[重复]

    这个问题在这里已经有答案了 我遇到了这个 Java 程序及其以意想不到的方式运行 以下程序计算 int 数组中元素对之间的差异 import java util public class SetTest public static void
  • Android Studio 在编译时未检测到支持库

    由于 Android Studio 将成为 Android 开发的默认 IDE 因此我决定将现有项目迁移到 Android studio 中 项目结构似乎不同 我的项目中的文件夹层次结构如下 Complete Project gt idea
  • JNI 不满意链接错误

    我想创建一个简单的 JNI 层 我使用Visual studio 2008创建了一个dll Win 32控制台应用程序项目类型 带有DLL作为选项 当我调用本机方法时 出现此异常 Exception occurred during even
  • 如何在jsp代码中导入java库?

    我有以下jsp代码 我想添加 java io 等库 我怎样才能做到这一点
  • Microsoft Graph 身份验证 - 委派权限

    我可以使用 Microsoft Graph 访问资源无需用户即可访问 https developer microsoft com en us graph docs concepts auth v2 service 但是 此方法不允许我访问需
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • 归并排序中的递归:两次递归调用

    private void mergesort int low int high line 1 if low lt high line 2 int middle low high 2 line 3 mergesort low middle l
  • 尝试使用 Ruby Java Bridge (RJB) gem 时出现错误“无法创建 Java VM”

    我正在尝试实现 Ruby Java Bridge RJB gem 来与 JVM 通信 以便我可以运行 Open NLP gem 我在 Windows 8 上安装并运行了 Java 所有迹象 至少我所知道的 都表明 Java 已安装并可运行
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 使用 AWS Java SDK 为现有 S3 对象设置 Expires 标头

    我正在更新 Amazon S3 存储桶中的现有对象以设置一些元数据 我想设置 HTTPExpires每个对象的标头以更好地处理 HTTP 1 0 客户端 我们正在使用AWS Java SDK http aws amazon com sdkf
  • org.jdesktop.application 包不存在

    几天以来我一直在构建一个 Java 桌面应用程序 一切都很顺利 但是今天 当我打开Netbeans并编译文件时 出现以下编译错误 Compiling 9 source files to C Documents and Settings Ad
  • 应用程序关闭时的倒计时问题

    我制作了一个 CountDownTimer 代码 我希望 CountDownTimer 在完成时重新启动 即使应用程序已关闭 但它仅在应用程序正在运行或重新启动应用程序时重新启动 因此 如果我在倒计时为 00 10 分钟 秒 时关闭应用程序
  • Keycloak - 自定义 SPI 未出现在列表中

    我为我的 keycloak 服务器制作了一个自定义 SPI 现在我必须在管理控制台上配置它 我将 SPI 添加为模块 并手动安装 因此我将其放在 module package name main 中 并包含 module xml 我还将其放
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour
  • 如何修复“sessionFactory”或“hibernateTemplate”是必需的问题

    我正在使用 Spring Boot JPA WEB 和 MYSQL 创建我的 Web 应用程序 它总是说 sessionFactory or hibernateTemplate是必需的 我该如何修复它 我已经尝试过的东西 删除了本地 Mav
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe
  • JAVA - 如何从扫描仪读取文件中检测到“\n”字符

    第一次海报 我在读取文本文件的扫描仪中读取返回字符时遇到问题 正在读取的文本文件如下所示 test txt start 2 0 30 30 1 1 90 30 0 test txt end 第一行 2 表示两个点 第二行 位置索引 0 xp

随机推荐

  • Verilog HDL运算符

    一 逻辑运算符 逻辑与 逻辑或 逻辑非 二 关系运算符 逻辑相等 逻辑不等 全等 不全等 和 可以比较含有x和z的操作数 在模块的功能仿真中有着广泛的应用 三 位运算符 非 与 或 异或 同或 四 拼接运算符 s1 s2 sn 五 一元约简
  • Python数据可视化:豆瓣电影TOP250

    欢迎关注天善智能 我们是专注于商业智能BI 人工智能AI 大数据分析与挖掘领域的垂直社区 学习 问答 求职一站式搞定 对商业智能BI 大数据分析挖掘 机器学习 python R等数据领域感兴趣的同学加微信 tstoutiao 邀请你进入数据
  • eclipse 使用maven构建 springboot +swagger

    swagger用于定义API文档 好处 1 前后端分离开发 2 API文档非常明确 3 测试的时候不需要再使用URL输入浏览器的方式来访问Controller 4 传统的输入URL的测试方式对于post请求的传参比较麻烦 当然 可以使用po
  • vue 记住密码下次自动登录

    div div
  • <HarmonyOS第一课>运行Hello World课后作业

    前言 HarmonyOS应用开发者基础认证课程课后习题 仅供参考 也欢迎各位小伙伴讨论指正 习题 判断题 1 DevEco Studio是开发HarmonyOS应用的一站式集成开发环境 正确 True 2 main pages json存放
  • [Qt]基础数据类型和信号槽

    文章目录 1 Qt基本结构 1 1 Qt本有项目 1 1 1 项目文件 pro 1 1 2 main cpp 1 1 3 mainwindow ui 1 1 4 mainwindow h 1 1 5 mainwindow cpp 1 2 Q
  • 使用libvirt管理KVM虚拟机

    使用libvirt管理KVM虚拟机 一 安装虚拟化管理工具 1 yum install virt manager libvirt libvirt python python virtinst 1 kmod kvm kvm kernel mo
  • 微信小程序wx.canvasToTempFilePath压缩上传图片,ios压缩成功但是数据sm2加密后无法发起请求,安卓一切正常

    问题以及解决 吐槽遇到的问题 在写微信小程序的时候 采用wx canvasToTempFilePath压缩图片且上传的时候 安卓一切正常 我在开发工具上也一切正常 偏偏ios上就不正常 不正常不是指压缩失败 而是明明也压缩成功了 竟然发不起
  • linux设备驱动makefile入门解析

    以下内容仅作参考 能力有限 如有错误还请纠正 对于一个普通的linux设备驱动模块 以下是一个经典的makefile代码 使用下面这个makefile可以 完成大部分驱动的编译 使用时只需要修改一下要编译生成的驱动名称即可 只需修改obj
  • 关于socket大数据收发解决方案

    关于socket大数据收发 现在遇到个问题 我们这边是做客户端的 服务器端是socket 不是我们写的 看不到源码 走的是tcp协议 我们的socket客户端在接收大数据 大约大于5000个byte 的时候总是不能一次性的接收所有的数据 一
  • 知乎 爬虫

    import requests from pyquery import PyQuery as pq def getHtml url try headers User Agent Mozilla 5 0 Macintosh Intel Mac
  • 远程桌面出现了内部错误有哪些解决方法?

    远程桌面连接出现了内部错误解决方法 在使用Windows自带远程桌面连接时 有时会遇到 远程桌面出现了内部错误 这一问题 许多用户不知道如何解决远程桌面连接出现了内部错误 这里我们整理了五种有效的解决方法 分享出来以供参考 方法一 重启远程
  • ETL使用Kettle处理银行信用卡申请项目

    一 项目概述 对当天申请信用卡人员进行信息校对 对不符合人员进行风险标注 无风险人员信息根据所在地区进行分表 交付 信息来源 1 web端 银行网页申请 2 移动端 网银 手机银行 3 三方 各类门户网站 手机APP 4 柜台 人工柜台 A
  • 利用GIT钩子函数实现自动部署或其他操作

    1 Server端 第一步 创建初始化一个裸仓库 用来添加钩子函数 git init bare test git hook function git 第二步 通过裸仓库创建一个用来存放代码的仓库 git init test git hook
  • latex算法步骤,子代码编号及修改算法框的宽度

    看了官方文档和网上一下资料 对于一个步骤下面有好多子步骤的算法 大多是通过for循环与while判断实现的 而且对于for下面的每一步骤没有重新编码 感觉很乱 不好看 论文的参考文有下图的结构 感觉很好 可以一用 主要用到下面这个代码块 其
  • 被C语言的malloc给坑了

    事情是这样的 最近想用C语言实现一些数据结构 今天在写二叉树时在linux下使用gcc编码是没有任何问题的 然而当我在本地window使用clion编写时 同样的代码竟然不能用了 反复看了下代码没有任何问题 然后我把代码拷贝到linux中用
  • redis集群配置

    分片集群搭建 springboot集成redis 相关配置 spring redis timeout 3000 database 0 cluster node 127 0 0 1 7000 127 0 0 1 7001 127 0 0 1
  • SpringBoot 文件上传解决跨域问题

    后端解决跨域问题 在Controller接口上加上 CrossOrigin注解就可以 该注解可以加在类上 也可以加在方法上 一般的请求处理数据都没有问题 但是如果上传文件就会报跨域的错误 解决这个文件上传跨域的问题 就需要增加一个过滤器配置
  • django解决跨域的方法,django如何解决跨域问题,django如何跨域

    django 使三方工具包解决跨域问题 1 安装 pip install django cors headers 2 到django的配置文件settings py中配置 1 注册到app中 INSTALLED APPS corsheade
  • Thread.UncaughtExceptionHandler

    1 自定义Application继承Application 在清单文件中将默认的Application的android name 替换成自定义的Application对象名称即可 在Oncreate中写入要实现的内容 2 在编写APK程序时