Android跨进程通信Client Crash后Server端onDestroy
Posted learnframework
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android跨进程通信Client Crash后Server端onDestroy相关的知识,希望对你有一定的参考价值。
hi,粉丝朋友大家好!
好久没有给大家写blog了,哈哈,这里说声抱歉!实在家里比较忙,今天就来给大家分享一个跨进程专题课中学员问的一个问题,blog就来解答一下这个问题。
问题背景:
视频课程内容链接:https://ke.qq.com/course/package/51285?tuin=7d4eb354
binder跨进程专题的,binder的linktodeath相关
这里同学提出疑问:
1、为啥这个跨进程通信时候client端crash了居然会导致server端的Service执行onDestroy? 2、而且为什么onDestroy了进程还在?
其实这个同学相对还是看视频非常专心的,注意到了这个细节。
这里其实要分析出这个问题并不难,我们首先可以来回答相对好回到的问题2:
为什么onDestroy了进程还在?
这个其实就是很多同学容易犯的一个错误,就是认为Activity执行onDestroy了就说明进程退出了,进程也会死了。其实不是哈,onDstroy只是属于进程里面的一个组件的生命周期完毕,大家注意哈,这里说的一个组件而不是进程的生命周期,即进程不会因为组件的onDestroy而进程也died,所以这里大家要注意哈
接下来在分析第一个问题
为啥这个跨进程通信时候client端crash了居然会导致server端的Service执行onDestroy?
总结一下就是为啥客户端死了会导致Service组件执行onDestroy,其实要想通这个问题并不难,首先从宏观上来看:
客户端 —bindService—才启动的Serivce执行的onCreate和onBind,但是现在客户端死了,那么大家想想那这个Serivce组件是不也应该要unbind和onDestroy呢?是不是这样想也其实挺合理
但是这个只是宏观上的一个理解感觉这样设计合理,但是请问老师你是嘴巴说么,有没有证据证明你说的这个,其实就是那句程序员名言:
talk is cheap,show me the code!
哈哈,那接下来就看我是show the code
分析步骤:
1、服务端service的onDestroy执行是谁调用过来的?
这个比较简单其实就使用课程经常使用的普通打印堆栈就可以
022-07-23 00:18:10.333 22650-22650/com.example.servicedemo I/test1: MyService onDestroy
java.lang.Exception
at com.example.servicedemo.MyService.onDestroy(MyService.java:126)
at android.app.ActivityThread.handleStopService(ActivityThread.java:4669)
at android.app.ActivityThread.access$2100(ActivityThread.java:247)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2096)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
大家发现这里其实是ActivityThread.handleStopService,这里其实大家大概知道,它对应的其实是:
public final void scheduleStopService(IBinder token)
sendMessage(H.STOP_SERVICE, token);
scheduleStopService这个方法调用导致,而scheduleStopService其实属于systemserver跨进程通信调用过来的
那么接下来就应该去framework中去搜索一下谁调用了scheduleStopService
test@test:~/aosp/frameworks$ grep scheduleStopService ./ -rn
./base/boot/hiddenapi/hiddenapi-max-target-o.txt:1933:Landroid/app/ActivityThread$ApplicationThread;->scheduleStopService(Landroid/os/IBinder;)V
./base/boot/hiddenapi/hiddenapi-max-target-o.txt:6200:Landroid/app/IApplicationThread$Stub$Proxy;->scheduleStopService(Landroid/os/IBinder;)V
./base/boot/hiddenapi/hiddenapi-max-target-o.txt:6254:Landroid/app/IApplicationThread$Stub;->TRANSACTION_scheduleStopService:I
./base/boot/boot-image-profile.txt:862:HSPLandroid/app/ActivityThread$ApplicationThread;->scheduleStopService(Landroid/os/IBinder;)V+]Landroid/app/ActivityThread;Landroid/app/ActivityThread;
./base/services/core/java/com/android/server/am/ActiveServices.java:4303: r.app.getThread().scheduleStopService(r);
./base/config/boot-image-profile.txt:862:HSPLandroid/app/ActivityThread$ApplicationThread;->scheduleStopService(Landroid/os/IBinder;)V+]Landroid/app/ActivityThread;Landroid/app/ActivityThread;
./base/core/java/android/app/ActivityThread.java:1085: public final void scheduleStopService(IBinder token)
./base/core/java/android/app/IApplicationThread.aidl:73: void scheduleStopService(IBinder token);
./base/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java:445: public void scheduleStopService(IBinder iBinder) throws RemoteException
大家可以看出结果其实非常明确就是
./base/services/core/java/com/android/server/am/ActiveServices.java:4303: r.app.getThread().scheduleStopService®;
即ActiveServices中进行了调用的,所以我们就好办,要么打印堆栈也可以,或者大家直接我经常交大家的采用更加先进的debug systemserver也可以
这里我们采用debug方式:
具体是怎么调用的大家可以看一下堆栈然后自己跟一下就可以
大概意思就是:
systemserver其实也对client的binder对象进行了linkToDeath,当client crash 时候systemserver也是要对这个进程Application修改记录信息进行扫尾处理,cleanup的,这里面就包含了我们今天问题Service执行onDestroy,因为Serivce本身是由Client发起的绑定拉起,
*## 而且也没有其他客户端绑定Service了 *
,当然唯一的链条Client如果已经died了,那么Service也就没有再存在,执行对应的unbind和onDestroy
新课程优惠获取请加入qq群:422901085(获取demo源码)
以上是关于Android跨进程通信Client Crash后Server端onDestroy的主要内容,如果未能解决你的问题,请参考以下文章
Android跨进程通信Client Crash后Server端onDestroy
Android 跨进程通信-从源码分析AIDL跨进程通信实现