我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android AIDL通信DeadObjectException解决方法是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android AIDL通信DeadObjectException解决方法是什么

这篇文章主要介绍了Android AIDL通信DeadObjectException解决方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android AIDL通信DeadObjectException解决方法是什么文章都会有所收获,下面我们一起来看看吧。

    崩溃来源

    首先,这个崩溃的意思是,多进程在进行跨进程Binder通信的时候,发现通信的Binder对端已经死亡了。

    抛出异常的Java堆栈最后一行是BinderProxy.transactNative,所以我们从这个方法入手,看看崩溃是在哪里产生的。

    很显现,transactNative对应的是一个native方法,我们找到对应的native方法,在android_util_Binder.cpp中。

    static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException{    // 如果data数据为空,直接抛出空指针异常    if (dataObj == NULL) {        jniThrowNullPointerException(env, NULL);        return JNI_FALSE;    }    // 将Java层传入的对象转换为C++层的指针,如果转换出错,中断执行,返回JNI_FALSE    Parcel* data = parcelForJavaObject(env, dataObj);    if (data == NULL) {        return JNI_FALSE;    }    Parcel* reply = parcelForJavaObject(env, replyObj);    if (reply == NULL && replyObj != NULL) {        return JNI_FALSE;    }    // 获取C++层的Binder代理对象指针    // 如果获取失败,会抛出IllegalStateException    IBinder* target = getBPNativeData(env, obj)->mObject.get();    if (target == NULL) {        jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");        return JNI_FALSE;    }    // 调用BpBinder对象的transact方法    status_t err = target->transact(code, *data, reply, flags);    // 如果成功,返回JNI_TRUE,如果失败,返回JNI_FALSE    if (err == NO_ERROR) {        return JNI_TRUE;    } else if (err == UNKNOWN_TRANSACTION) {        return JNI_FALSE;    }    // 处理异常情况的抛出    signalExceptionForError(env, obj, err, true , data->dataSize());    return JNI_FALSE;}

    可以看到,这个方法主要做的事情是:

    • Java层传入的data,转换成C++层的指针

    • 获取C++层的Binder代理对象

    • 调用BpBinder对象的transact方法

    • 处理transact的结果,抛出异常

    接下来我们看看,BpBindertransact方法。

    status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    // 首先判断Binder对象是否还存活,如果不存活,直接返回DEAD_OBJECT    if (mAlive) {            ...            status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);            return status;    }    return DEAD_OBJECT;}

    transact的具体方法,我们这里先不讨论。我们可以看到,在这里会判断当前的Binder对象是否alive,如果不alive,会直接返回DEAD_OBJECT的状态。

    返回的结果,在android_util_BindersignalExceptionForError中处理。

    void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,        bool canThrowRemoteException, int parcelSize){       // 省略其他异常处理的代码        ....        case DEAD_OBJECT:            // DeadObjectException is a checked exception, only throw from certain methods.            jniThrowException(env, canThrowRemoteException                    ? "android/os/DeadObjectException"                            : "java/lang/RuntimeException", NULL);            break;}

    这个方法,其实包含非常多异常情况的处理。为了看起来更清晰,这里我们省略了其他异常的处理逻辑,只保留了DEAD_OBJECT的处理。可以很明显的看到,在这里我们抛出了DeadObjectException异常。

    解决方法

    通过前面的源码分析,我们知道DeadObjectException是发生在,当我们调用transact接口发现Binder对象不再存活的情况。

    解决方案也很简单,就是当这个Binder对象死亡之后,不再调用transact接口。

    方法1 调用跨进程接口之前,先判断Binder是否存活

    这个方案比较简单粗暴,就是在多有调用跨进程接口的地方,都加一个Binder是否存活的判断。

            if (mService != null && mService.asBinder().isBinderAlive()) {            mService.test();        }

    我们来看下isBinderAlive的源码,就是判断mAlive标志位是否为0。

    bool BpBinder::isBinderAlive() const{    return mAlive != 0;}

    方法2 监听Binder死亡通知

    先初始化一个DeathRecipient,用来监听死亡通知。

        private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {        @Override        public void binderDied() {            // 解绑当前监听,重新启动服务            mService.asBinder().unlinkToDeath(mDeathRecipient, 0);            if (mService != null)                bindService(new Intent("com.service.bind"), mService, BIND_AUTO_CREATE);        }    };

    在这个死亡监听里,我们可以选择几种处理方式:

    • 什么都不做,直接将mService设置为空

    • 再次尝试启动和绑定服务

    onServiceConnected方法中,注册死亡监听:

    public void onServiceConnected(ComponentName name, IBinder service) {              mService = IServiceInterface.Stub.asInterface(service);         //获取服务端提供的接口    try {        // 注册死亡代理        if(mService != null){            service.linkToDeath(mDeathRecipient, 0);         }           } catch (RemoteException e) {        e.printStackTrace();    }}

    关于“Android AIDL通信DeadObjectException解决方法是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“Android AIDL通信DeadObjectException解决方法是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Android AIDL通信DeadObjectException解决方法是什么

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Android AIDL通信DeadObjectException解决方法是什么

    这篇文章主要介绍了Android AIDL通信DeadObjectException解决方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Android AIDL通信DeadObjectException
    2023-07-05

    Android AIDL通信DeadObjectException解决方法示例

    这篇文章主要为大家介绍了Android AIDL通信DeadObjectException解决的方法示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-09

    Android编程实现AIDL(跨进程通信)的方法详解

    本文实例讲述了Android编程实现AIDL(跨进程通信)的方法。分享给大家供大家参考,具体如下: 一. 概述: 跨进程通信(AIDL),主要实现进程(应用)间数据共享功能。 二. 实现流程: 1. 服务器端实现: (1)目录结构,如下图:
    2022-06-06

    android多进程通信的方法是什么

    Android中多进程通信的方法有以下几种:1. 使用Messenger:Messenger是一种轻量级的进程间通信(IPC)机制,使用Handler和Message进行通信。它可以在不同进程之间传递Message对象,实现进程间的数据交换
    2023-10-10

    android多线程通信的方法是什么

    在Android中,多线程通信可以使用以下几种方法:1. Handler:Handler是用于在不同线程之间传递消息的机制。可以在主线程中创建一个Handler对象,并调用其post()方法发送消息,在其他线程中创建一个Handler对象,
    2023-08-18

    vue的通信方法是什么

    今天小编给大家分享一下vue的通信方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。通信方法:1、子组件设置props
    2023-07-04

    Java NIO Socket通信的方法是什么

    这篇文章主要讲解了“Java NIO Socket通信的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java NIO Socket通信的方法是什么”吧!服务器代码:import
    2023-06-17

    Linux进程通信的方法是什么

    本篇内容介绍了“Linux进程通信的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Linux进程通信具体方法1.管道管道分为有名管
    2023-06-28

    android读取短信的方法是什么

    Android读取短信的方法可以通过使用 BroadcastReceiver 和 ContentResolver 两种方式来实现。1. 使用 BroadcastReceiver:创建一个继承自 BroadcastReceiver 的类,重写
    2023-08-12

    golang进程间通信的方法是什么

    Golang中可以使用多种方式进行进程间通信,包括:1. Channel(通道):Golang的Channel是一种用于在协程之间进行通信和同步的机制。使用Channel可以在不同的goroutine之间发送和接收数据。通过创建一个Chan
    2023-08-23

    docker容器间通信的方法是什么

    Docker容器间通信的方法有以下几种:使用容器名称或ID进行通信:每个Docker容器都有一个唯一的名称或ID,可以使用这个名称或ID来进行容器间的通信。例如,可以使用容器名称作为主机名在容器之间进行通信。使用Docker网络进行通信:D
    2023-10-25

    java线程间通信的方法是什么

    Java线程间通信的方法有以下几种:使用共享变量:多个线程共享同一个变量,通过对变量的读写操作来实现线程间的通信。例如,一个线程负责生产数据,另一个线程负责消费数据,它们通过共享一个队列来实现数据的传递。使用wait()和notify()
    java线程间通信的方法是什么
    2023-10-28

    angular模块间通信的方法是什么

    在Angular中,模块间通信的方法有多种,下面是一些常用的方法:1. 通过共享服务进行通信:创建一个共享服务,可以在多个模块中注入并共享数据。可以在服务中定义一个可观察对象或者使用Subject来传递数据,并在需要接收数据的模块中进行订阅
    2023-10-11

    常见的Linux进程通信方法是什么

    这篇文章主要为大家分析了常见的Linux进程通信方法是什么的相关知识点,内容详细易懂,操作细节合理,具有一定参考价值。如果感兴趣的话,不妨跟着跟随小编一起来看看,下面跟着小编一起深入学习“常见的Linux进程通信方法是什么”的知识吧。进程虽
    2023-06-28

    Android bindservice失败的原因和解决方法是什么

    Android bindService 失败的原因和解决方法可能有多种。1. 原因:Service 未正确声明或注册。如果 Service 没有在 AndroidManifest.xml 文件中正确声明或注册,那么 bindService
    2023-08-17

    android内存泄漏的原因及解决方法是什么

    Android内存泄漏的原因可能有以下几个:1. 长生命周期的对象持有短生命周期的引用:当一个长生命周期的对象持有了一个短生命周期对象的引用,导致短生命周期对象无法被垃圾回收,从而造成内存泄漏。2. 静态引用持有对象的引用:当一个静态变量持
    2023-08-08

    android界面卡顿的原因及解决方法是什么

    Android界面卡顿的原因可能有很多,包括以下几个常见的原因:1. 主线程阻塞:当在主线程中执行耗时操作或者频繁的UI更新时,可能会导致界面卡顿。例如,网络请求、数据库操作、图片加载等耗时操作应该放在子线程中执行。2. 内存泄漏:当一个A
    2023-10-18

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录