Android System crash DeadSystemException(Service/Activity/终极解决方案)

DeadSystemException

The core Android system has died and is going through a runtime restart. All running apps will be promptly killed.
Android 核心系统服务已经死亡,正在重启中。全部正在运行的app即将被kill杀死。

更多请阅读,DeadSystemException官方介绍

chatgpt给出的解决答案
Android中的DeadSystemException是一种非常严重的异常,表示系统已经崩溃。如果不进行处理,应用程序将会崩溃并退出。

处理方式:

  1. 捕获该异常:使用try-catch来捕获DeadSystemException异常,或者注册一个UncaughtExceptionHandler来处理未捕获的异常
  2. 根据产品需求进行业务逻辑处理:进行相应的处理,例如输出错误日志或者提示用户重新启动应用程序。

1.service create 发生该异常:

在这里插入图片描述
先来看下调用栈中抛出异常的地方:
/frameworks/base/core/java/android/app/ActivityThread.java 中handleCreateService():
在这里插入图片描述
在这里插入图片描述
从源码可知 :

  1. app 进程已经完成对service#oncreate()过程,接着与ams 通过binder通讯,发生了DeadObjectException 从而抛出了DeadSystemException。
  2. ActivityThread 中对service创建过程有异常处理机制try-catch ,会判断Instrumentation 是否拦截该异常。

为了进一步了解原因,接着查看bugly上该异常中捕获的日志,发现有几条有效日志:

//系统服务已经die死亡
AndroidRuntime: FATAL EXCEPTION: main
AndroidRuntime: Process: com.android.systemui, PID: 19210
AndroidRuntime: DeadSystemException: The system died; earlier logs will point to the root cause
AppErrors: Process com.android.systemui has crashed too many times: killing!//binder 通讯异常抛出日志
JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 104)

根据分析,推断系统服务已经死亡,app进程通过binder与之通讯,会抛出DeadSystemException。

根据FAILED BINDER TRANSACTION检索,找/frameworks/base/core/jni/android_util_Binder.cpp
signalExceptionForError():
在这里插入图片描述
从binder通讯源码中可知,当遇到异常返回status(failed_transansaction 和dead_object)时, 会抛出DeadObjectException异常。另外,单次读写超过200k的binder数据,就会抛出TransactionTooLargeException 异常;

原因推断:当app进程创建service 成功后,与ams 通讯过程中,binder 发生异常状态status failed_transansaction,从而抛出异常导致。

解决方案:
采用hook 方式,代理Instrumentation 捕获该异常:

 /*** 自定义 Instrumentation 子类,* 拦截对Activity和Service的系统异常拦截*/private static class InstrumentationImpl extends Instrumentation{@Overridepublic boolean onException(Object obj, Throwable e) {return isInterruptException(e);}public static void hookInstrumentation(){//基本上发生在7.0和7.1设备上if (Build.VERSION.SDK_INT==Build.VERSION_CODES.N_MR1||Build.VERSION.SDK_INT==Build.VERSION_CODES.N){try {Instrumentation ins = new InstrumentationImpl();Class cls = Class.forName("android.app.ActivityThread");Method mthd = cls.getDeclaredMethod("currentActivityThread", (Class[]) null);Object currentAT = mthd.invoke(null, (Object[]) null);Field mInstrumentation = currentAT.getClass().getDeclaredField("mInstrumentation");mInstrumentation.setAccessible(true);mInstrumentation.set(currentAT, ins);}catch (Exception e){e.printStackTrace();}}}}
}
private static boolean isInterruptException(Throwable e){if (e.toString().contains("DeadSystemException")){//拦截DeadSystemExceptionreturn true;}return false;
}

以上代码,在Application的oncreate()中调用。

还有其他hook 方式,ActivityThread#H 的handler callBack ,也可以通用实现以上效果;

捕获该异常后,需要启动的服务无法启动,Bugly 不会捕捉到该异常,但app进程很可能会被杀死。

2.activity destory 发生该异常

先查看调用栈:
在这里插入图片描述
查看下crash 所在的源码:
在这里插入图片描述
与前面的问题有些不同,当app 进程已经完成Activity销毁过程后,通知ams 过程中,发生系统进程,死亡异常则直接抛出。

解决方案
App 销毁Activity过程中没有异常捕捉机制,但该调用栈是在ActivityThread 中名为H 的handler中调用的,因此考虑hook 进行异常捕获。

再查看Handler的源码,发现可以为它设置callBack便可以拦截其handleMessage()调用。

在这里插入图片描述
编写代码如下所示:

private static class  CallBackImpl implements Handler.Callback{private  Handler activityThreadHandler;public CallBackImpl(Handler activityThreadHandler) {this.activityThreadHandler = activityThreadHandler;}@Overridepublic boolean handleMessage(Message msg) {try {activityThreadHandler.handleMessage(msg); }catch (Exception e){if (!isInterruptException(e)){//不被拦截的异常,继续抛出throw  e; }   }return true;}public static void hook(){try {if (Build.VERSION.SDK_INT==Build.VERSION_CODES.N_MR1||Build.VERSION.SDK_INT==Build.VERSION_CODES.N){//获取到ActivityThreadClass<?> ActivityThreadClass = Class.forName("android.app.ActivityThread");Field sCurrentActivityThreadField = ActivityThreadClass.getDeclaredField("sCurrentActivityThread");sCurrentActivityThreadField.setAccessible(true);Object ActivityThread = sCurrentActivityThreadField.get(null);//获取到ActivityThread中的handlerField mHField=ActivityThreadClass.getDeclaredField("mH");mHField.setAccessible(true);Handler mHandler=(Handler) mHField.get(ActivityThread);//给handler添加callback监听器,拦截Field mCallBackField = Handler.class.getDeclaredField("mCallback");mCallBackField.setAccessible(true);mCallBackField.set(mHandler, new CallBackImpl(mHandler));}}catch (Exception e){e.printStackTrace();}}
}private static boolean isInterruptException(Throwable e){if (e.toString().contains("DeadSystemException")){//拦截DeadSystemExceptionreturn true;}return false;
}

以上代码,在Application的oncreate()中调用

3.activity stop发生该异常

在这里插入图片描述
查看源码:
在这里插入图片描述
StopInfo 这个任务是在ActivityThread 执行Activity onstop状态时添加的:
在这里插入图片描述
handleStopActivity() 是在ActivityThread中H的handler中调用的。

解决方案
因StopInfo是runnable接口,无法通过Handler的handleMessage()函数进行拦截,因此考虑直接代理H 这个Handler , 通过dispatchMessage()分发,传递给H处理,进行异常捕捉。

private static class HandlerImpl extends Handler {private Handler proxy;public HandlerImpl(Handler proxy) {super(proxy.getLooper());this.proxy = proxy;}@Overridepublic void dispatchMessage(@NonNull Message msg) {try {proxy.dispatchMessage(msg);} catch (Exception e) {if (!isInterruptException(e)) {//不被拦截的异常,继续抛出throw e;}}}public static void hook() {try {if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1 || Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {//获取到ActivityThreadClass<?> ActivityThreadClass = Class.forName("android.app.ActivityThread");Field sCurrentActivityThreadField = ActivityThreadClass.getDeclaredField("sCurrentActivityThread");sCurrentActivityThreadField.setAccessible(true);Object ActivityThread = sCurrentActivityThreadField.get(null);//获取到ActivityThread中的handlerField mHField = ActivityThreadClass.getDeclaredField("mH");mHField.setAccessible(true);Handler mHandler = (Handler) mHField.get(ActivityThread);mHField.set(ActivityThread, new HandlerImpl(mHandler));}} catch (Exception e) {e.printStackTrace();}}
}
private static boolean isInterruptException(Throwable e) {if (e.toString().contains("DeadSystemException")) {//拦截DeadSystemExceptionreturn true;}return false;
}

Hook H 这个Handler 可以解决Activity或者Service 生命周期中该异常的捕获。在Application的oncreate()中调用。

4. (终极解决方案,捕获任何地方发生该问题的调用栈)

实际上可能其他的线程或者其他的handler 中调用跨进程有关的api都可能会遇到该问题,单纯hook ActivityThread中Handler是无法解决的。
终极解决方案:通过主线程的异常处理器,捕获该异常,自定义Thread.UncaughtExceptionHandler。

/*** 终极解决方案*/
private static class ExceptionHandlerImpl implements Thread.UncaughtExceptionHandler{private final Thread.UncaughtExceptionHandler mOldHandler;public ExceptionHandlerImpl(Thread.UncaughtExceptionHandler mOldHandler) {this.mOldHandler = mOldHandler;}@Overridepublic void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {if (isInterruptException( e)) {// 异常逻辑 1: 继续执行,进程不结束resumeMainThreadLoop();// restartApp() 或者直接中断该进程,进行重启重启该app 的逻辑2return;}if (mOldHandler != null) {mOldHandler.uncaughtException(t, e);}}private void restartApp(Context context){// 重新启动应用程序或者系统服务final Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent);// 退出应用程序或者停止服务System.exit(0);}private void resumeMainThreadLoop() {if (Looper.myLooper() != Looper.getMainLooper()) {return;}try {Looper.loop();} catch (Exception e) {uncaughtException(Thread.currentThread(), e);}}public static void init(){//在bugly初始化或者自定义crash上报组件之后调用Thread.UncaughtExceptionHandler mOldHandler = Thread.getDefaultUncaughtExceptionHandler();if (!(mOldHandler instanceof ExceptionHandlerImpl)) {Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandlerImpl(mOldHandler));}}
}

以上代码在bugly或者异常捕获组件之后调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/46988.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chatgpt赋能python:Python实现网络断开:如何使用Python断开网络连接

Python实现网络断开&#xff1a;如何使用Python断开网络连接 在某些情况下&#xff0c;我们需要暂时断开网络连接。这可能是因为我们需要测试某种网络应用程序或进行网络安全探索&#xff0c;或者需要限制孩子上网时间。在这些情况下&#xff0c;Python提供了一种断开网络连接…

libpaho-mqtt c 库使用注意事项

mqtt断线重连&#xff1a; 需要在连接的时候设置三个参数. 重连间隔单位为秒。 在例程里 MQTTAsync client; MQTTAsync_connectOptions conn_opts MQTTAsync_connectOptions_initializer; MQTTAsync_message pubmsg MQTTAsync_message_initializer; MQTTAsync_token to…

“大模型重塑时空产业,繁荣智能孪生世界”行业发展论坛成功举办

由中国地理信息产业协会时空信息智能云服务工作委员会主办、土豆数据科技集团承办、四川省地理信息产业协会和成都市勘察测绘研究院支持筹办&#xff0c;主题为“大模型重塑时空产业&#xff0c;繁荣智能孪生世界”的行业发展论坛&#xff0c;近日在成都成功举办。 “大模型重…

System.Net.Mail发送邮件失败所在

/**/ /// <summary> /// 注册时发送用户帐号跟密码 /// </summary> /// <param name"receiver">用户注册邮箱</param> /// <param name"username">用户名</param> /// <param name"password&q…

发送邮件失败提示validity check failed 处理

前几天发现发送邮件服务失效了&#xff0c;通过查看日志发现异常提示为Exception reading response 。 在本地开始调试排查原因。之前发送代码如下&#xff1a; public static void sendEmail(Map<String, Object> map) {/*** 参数配置--装信封写地址*/Properties prop …

outlook邮箱的权限异常

邮件项目上线后&#xff0c;出现了一些小bug。 产品找到我说有个outlook邮箱无法发送邮件&#xff0c;暂且就把这个邮箱称作是“bugoutlook.com”吧。 既然发送失败&#xff0c;第一时间就是拉取日志查看异常原因了&#xff0c;异常原因“Caused by: javax.mail.Authenticatio…

python smtp发送邮件,收件人和发件人不显示问题

使用smtp发送邮件时&#xff0c;在已发送邮件列表中&#xff0c;收件人信息显示“收件人未填写”&#xff0c;在邮件详情中也没有直接显示收件人信息&#xff0c;发件人也为空&#xff1a; 发送方显示&#xff1a; 收件方显示&#xff1a; 解决办法&#xff1a; 引入email.u…

Cannot connenct to relay host smtp.163.com (php邮件发送失败)

真是无语 搞了那么久&#xff0c;网上全部都说是 服务器php.ini 配置的问题&#xff0c;全tm都是抄的&#xff0c;误人子弟&#xff0c;好在 发现 该好贴&#xff0c;不过 阿里云 也真是 操蛋&#xff0c;屏蔽了25端口也不说&#xff0c;好吧&#xff01;可能是我 没注意到。 扯…

文旅虚拟数字人代言成新趋势,虚拟人应用覆盖文旅服务营销场景

数字科技高速发展的潮流中&#xff0c;文旅企业面临着加速数字化转型和业务增长的新机遇。随着元宇宙概念的火爆、虚拟技术的不断成熟&#xff0c;“虚拟数字人”依托于强可塑性、高成长性等特点&#xff0c;成为了文旅产业发展的新动能&#xff0c;并结合AR、VR等虚拟技术将线…

轻创AI数字人究竟有何不同?

AI数字人直播间带货的搭建其实十分简单&#xff0c;尤其对于那些已经熟悉无人直播的老手们来说&#xff0c;整个过程非常丝滑。 要实现AI数字人直播间带货&#xff0c;首先需要一款专业的AI数字人直播软件工具。 轻创AI数字人拥有出色的功能&#xff0c;能够帮助您轻松搭建数…

全球首款ChatGPT自行车!还是中国制造。。。。。

来源&#xff1a;量子位 万物皆可GPT的时代&#xff0c;这次轮到自行车了&#xff01; 一家专搞电助力自行车&#xff08;E-Bike&#xff09;的公司&#xff0c;已经把ChatGPT接入到自家最新产品中。 车身通过配备数字语音交互界面和内置扬声器&#xff0c;实现骑车同时与GPT聊…

git clone报错:Permission Denied (权限被拒绝)解决

参考文章 在使用git clone 命令出现该报错&#xff0c;解决方法比较清晰故作此记录。 步骤一&#xff1a;检查本地ssh key是否存在 打开git bash输入如下命令检查本地ssh key是否存在&#xff0c;若存在就如下所示&#xff0c;不存在就生成则执行步骤二&#xff0c;否则执行步…

自有品牌与新兴渠道双轮驱动,丽人丽妆提速起航

2023年4月12日&#xff0c;上海市电子商务行业协会评选出上海市数字商务优秀企业&#xff0c;丽人丽妆凭借在数智化营销领域的专业能力&#xff0c;荣获“上海市数字商务优秀企业”称号。 此次获奖&#xff0c;也反映了丽人丽妆以科技赋能企业高效运营&#xff0c;已经取得突出…

far-planner源码阅读笔记

一位刚刚会用ROS的小白阅读的第一个工程项目。 说明&#xff1a; 该附件的编写方法为set(CMAKE_BUILD_TYPE Debug)后通过vscode逐行调试。主机运行两个ros-noetic的docker容器&#xff0c;用一个容器调试far-planner另一个容器用于练习从far-planner源码中学到的知识&#xff0…

GPT-4救了我狗的命

Datawhale干货 最新&#xff1a;GPT应用、医学诊断&#xff0c;来源&#xff1a;量子位 这两天&#xff0c;一篇关于“GPT-4救了我狗的命”的帖子属实有点火&#xff1a; 短短一两天就有数千人转发&#xff0c;上万人点赞&#xff0c;网友在评论区讨论得热火朝天。 △ 是真狗命…

ChatGPT4救了我狗的命

来源&#xff1a;量子位 这两天&#xff0c;一篇关于 “GPT-4救了我狗的命” 的帖子属实有点火&#xff1a; 短短一两天就有数千人转发&#xff0c;上万人点赞&#xff0c;网友在评论区讨论得热火朝天。 △ 是真狗命&#xff0c;not人的“狗命”&#xff08;Doge&#xff09; 乍…

谷歌员工抱怨公司削减福利,CEO 回应称:“不要把乐趣等同于金钱”

整理 | 辛晓亮 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 上周&#xff0c;在谷歌全员大会上&#xff0c;有员工抱怨公司近期缩减员工福利&#xff0c;其中包括取消旅行、娱乐等津贴。员工们认为&#xff0c;谷歌已经基本走出疫情带来的影响&#xff0c;在公…

我问了 ChatGPT 一个问题:我生活在哪个世纪?

我问了 ChatGPT 一个问题&#xff1a;我生活在哪个世纪&#xff1f; ChatGPT 算得上最近科技圈最火的一个话题之一了。如是我也想赶时髦&#xff0c;体验一把 ChatGPT。 访问&#xff1a;https://chat.openai.com/&#xff0c;给了我一个&#xff1a; why? 在 net 上逛了逛…

【历史上的今天】7 月 27 日:模型检测先驱出生;微软收购 QDOS;第一张激光照排的中文报纸

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2022 年 7 月 27 日&#xff0c;在 1961 年的今天&#xff0c;IBM 推出了 IBM Selectric 电动打字机&#xff1b;Selectric 电动打字机是打字机界无可争议的游戏规则颠…

彼得·蒂尔将退出Meta董事会,2004年就投资扎克伯格

NEW 关注Tech逆向思维视频号 最新视频→【揭秘北京冬奥八大比赛场馆】 2月8日消息&#xff0c;美国当地时间周一&#xff0c;Facebook母公司Meta证实&#xff0c;风险投资家、Paypal联合创始人彼得泰尔(Peter Thiel)将退出其董事会&#xff0c;具体时间是Meta 2022年年度股东大…