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

这篇具有很好参考价值的文章主要介绍了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 发生该异常:

deadsystemexception,Android 应用层开发,android
先来看下调用栈中抛出异常的地方:
/frameworks/base/core/java/android/app/ActivityThread.java 中handleCreateService():
deadsystemexception,Android 应用层开发,android
deadsystemexception,Android 应用层开发,android
从源码可知 :

  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():
deadsystemexception,Android 应用层开发,android
从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{
        @Override
        public 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")){
        //拦截DeadSystemException
        return true;
    }
     return false;
}

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

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

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

2.activity destory 发生该异常:

先查看调用栈:
deadsystemexception,Android 应用层开发,android
查看下crash 所在的源码:
deadsystemexception,Android 应用层开发,android
与前面的问题有些不同,当app 进程已经完成Activity销毁过程后,通知ams 过程中,发生系统进程,死亡异常则直接抛出。

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

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

deadsystemexception,Android 应用层开发,android
编写代码如下所示:

private static class  CallBackImpl implements Handler.Callback{
    private  Handler activityThreadHandler;
    public CallBackImpl(Handler activityThreadHandler) {
        this.activityThreadHandler = activityThreadHandler;
    }
    @Override
    public 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){
            //获取到ActivityThread
            Class<?> ActivityThreadClass = Class.forName("android.app.ActivityThread");
            Field sCurrentActivityThreadField = ActivityThreadClass.getDeclaredField("sCurrentActivityThread");
            sCurrentActivityThreadField.setAccessible(true);
            Object ActivityThread = sCurrentActivityThreadField.get(null);
            //获取到ActivityThread中的handler
            Field 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")){
        //拦截DeadSystemException
        return true;
    }
     return false;
}

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

3.activity stop发生该异常:

deadsystemexception,Android 应用层开发,android
查看源码:
deadsystemexception,Android 应用层开发,android
StopInfo 这个任务是在ActivityThread 执行Activity onstop状态时添加的:
deadsystemexception,Android 应用层开发,android
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;
    }
    @Override
    public 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) {
                //获取到ActivityThread
                Class<?> ActivityThreadClass = Class.forName("android.app.ActivityThread");
                Field sCurrentActivityThreadField = ActivityThreadClass.getDeclaredField("sCurrentActivityThread");
                sCurrentActivityThreadField.setAccessible(true);
                Object ActivityThread = sCurrentActivityThreadField.get(null);
                //获取到ActivityThread中的handler
                Field 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")) {
        //拦截DeadSystemException
        return 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;
    }

    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
        if (isInterruptException( e)) {
            // 异常逻辑 1: 继续执行,进程不结束
            resumeMainThreadLoop();
            // restartApp() 或者直接中断该进程,进行重启重启该app 的逻辑2
            return;
        }
        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或者异常捕获组件之后调用。文章来源地址https://www.toymoban.com/news/detail-686517.html

到了这里,关于Android System crash DeadSystemException(Service/Activity/终极解决方案)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • system service exception蓝屏

    电脑蓝屏 问题是用户最为头疼的问题之一,而一般蓝屏问题都会有一个蓝屏终止代码也就是我们的常说的错误代码。那么如果遇到SYSTEM_SERVICE_EXCEPTION蓝屏怎么办呢? 解决方法一: 1、使用 Windows键+R打开运行,输入“control.exe”,点击确定,如下图: 2、选择“电源选项”,如

    2024年02月12日
    浏览(32)
  • Android Native crash触发原理及处理

    当程序执行以下操作,会触发native crash: 1)程序自己调用 abort() 函数触发,用于表示出现严重的错误或异常情况,需要终止程序执行 2)内存对齐错误或非法地址访问 3)零除错误(除数为零),浮点溢出或下溢出等 4)使用了非法的机器指令或指令参数不当而导致 5)进程试

    2024年01月15日
    浏览(25)
  • Android 查看ANR和Crash日志(adb bugreport)

    今天测试那儿出了个ANR,我自己手机没问题,很烦,定位不了位置。 于是还是得用ADB连接来看一下,之前用,但是老是会忘记,今天总结一下。 ADB命令查看应用包名_adb查看包名命令_岁月不待人的博客-CSDN博客 上面的连接是之前用adb后写的一篇常用的一些密令总结。 ANR的排

    2024年02月13日
    浏览(54)
  • Android 获取奔溃crash的日志(adb logcat或者dropbox)

    1.通过adb logcat 来获取 : 使用场景 :测试或者开发小伙伴 抓取。 先执行 adb logcat -c 清理缓存日志 接着,抓取当前时间段开始的日志: adb logcat -v time D:/crash.log 也可以抓取指定进程的日志: adb logcat -v time | find \\\"com.xxx\\\" D:/crash.log 其中 -v 和 time 是指log的v级别日志,也可用w 警告

    2024年02月08日
    浏览(44)
  • Activity之间数据回传【Android、activity回传、结合实例】

    在Android应用中,有时需要从一个Activity向另一个Activity传递数据,并在第二个Activity处理后将结果传递回第一个Activity。 这种情况下,我们可以使用 startActivityForResult() 和 onActivityResult() 方法来实现数据回传。 创建新的Android项目: 打开Android Studio并创建一个新的Android项目,确

    2024年02月08日
    浏览(34)
  • Android Activity启动流程一:从Intent到Activity创建

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 学习前,建议有相关知识储备: 【Android 基础】 应用(Application)启动流程 通过本文你可以学习到Activity启动流

    2024年02月10日
    浏览(35)
  • Android Activity的启动流程(Android-10)

    在Android开发中,我们经常会用到startActivity(Intent)方法,但是你知道startActivity(Intent)后Activity的启动流程吗?今天就专门讲一下最基础的startActivity(Intent)看一下Activity的启动流程,同时由于Launcher的启动后续和这里基本类似,就记录在一起。注意本章都是基于Android-10来讲解的。

    2024年01月17日
    浏览(37)
  • [Android 四大组件] --- Activity

    ​​Activity​​是一个Android的应用组件,它提供屏幕进行交互。每个Activity都会获得一个用于绘制其用户界面的窗口,窗口可以充满哦屏幕也可以小于屏幕并浮动在其他窗口之上。 一个应用通常是由多个彼此松散联系的Activity组成,一般会指定应用中的某个Activity为主活动,也

    2024年02月10日
    浏览(32)
  • Android --- Activity

    官方文档-activity Activity 提供窗口,供应在其中多个界面。此窗口通常会填满屏幕,但也可能小于屏幕并浮动在其他窗口之上。 大多数应用包含多个屏幕,这意味着它们包含多个 Activity。通常,应用中的一个 Activity 会被指定主 Activity,即用户启动应用时显示的第一个屏幕。然

    2024年04月23日
    浏览(57)
  • Android Activity启动过程详解

    1,《android系统启动流程简介》 2,《android init进程启动流程》 3,《android zygote进程启动流程》 4,《Android SystemServer进程启动流程》 5,《android launcher启动流程》 6,《Android Activity启动过程详解》 1,《Android 源码下载和编译》 2,《android 11源码编译和pixel3 刷机》 3,《Andro

    2024年02月09日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包