07-22 04:38:07.933 1579 3338 E JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 352)
07-22 04:38:07.933 1579 3338 W BroadcastQueue: Can't deliver broadcast to com.android.systemui (pid 2160). Crashing it.
07-22 04:38:07.934 1579 3338 W BroadcastQueue: Failure sending broadcast Intent { act=android.intent.action.TIME_TICK flg=0x50000014 (has extras) }
07-22 04:38:07.934 1579 3338 W BroadcastQueue: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at android.os.BinderProxy.transactNative(Native Method)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at android.os.BinderProxy.transact(Binder.java:618)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at android.app.ApplicationThreadProxy.scheduleRegisteredReceiver(ApplicationThreadNative.java:1211)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:489)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:702)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:1002)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:799)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.ActivityManagerService.finishReceiver(ActivityManagerService.java:19153)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:528)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2909)
07-22 04:38:07.934 1579 3338 W BroadcastQueue: at android.os.Binder.execTransact(Binder.java:565)
07-22 04:38:07.937 2160 2160 D AndroidRuntime: Shutting down VM
07-22 04:38:07.953 2160 2625 E JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 136)
--------- beginning of crash
07-22 04:38:07.972 2160 2160 E AndroidRuntime: FATAL EXCEPTION: main
07-22 04:38:07.972 2160 2160 E AndroidRuntime: Process: com.android.systemui, PID: 2160
07-22 04:38:07.972 2160 2160 E AndroidRuntime: android.app.RemoteServiceException: can't deliver broadcast
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1690)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at android.os.Looper.loop(Looper.java:160)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6252)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
07-22 04:38:07.972 2160 2160 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:788)
该错误发生在BroadcastQueue类中,当它通过绑定器调用ScheduleRegisteredReceiver时,会引发DeadobjectException。就像日志上说的:小包裹上的事务失败;远程进程可能已经死了,但是如果com.android.systemui进程已经死了,为什么还要抛出runtimeexception?
最佳答案
我终于找到了根本原因,它发生在binder内核中。
目前,我发现了两个原因,一个是可以导致广播队列中引发DeadobjectException,另一个是在应用程序的ActivityThread中引发RemoteServiceException之后:
当AMS向ActivityThread发送单向绑定器调用以触发BroadcastReceiver.onReceive时,没有更多的异步空间来执行绑定器事务。
相关代码如下:
kernel/msm-4.4/drivers/android/binder_alloc.c
290 if (is_async &&
291 alloc->free_async_space < size + sizeof(struct binder_buffer)) {
292 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
293 "%d: binder_alloc_buf size %zd failed, no async space left\n",
294 alloc->pid, size);
295 eret = ERR_PTR(-ENOSPC);
296 goto error_unlock;
297 }
因此,这不会“最终破坏系统稳定”。它只会影响应用程序本身。
由于BroadcastQueue向ActivityThread发送ScheduleCash绑定器调用,用户应用程序已被强制关闭。这个问题的根本原因是应用程序端没有绑定缓冲区,因为一些绑定线程占据了它的大部分。
可以通过以下步骤触发错误:
process1向process2发送大数据(例如980kb),process2需要休眠30秒,并且不会释放大绑定缓冲区。
process1向process2发送广播,由例如50kb的数据组成。这将超出make缓冲区容量1016kb,因为980kb+50kb大于缓冲区容量。
BroadcastQueue将抛出一个DeadobjectException,然后将ScheduleCash传递给应用程序端的ActivityThread。
代码如下:
kernel/msm-4.4/drivers/android/binder_alloc.c
315 if (best_fit == NULL) {
...
341 pr_err("%d: binder_alloc_buf size %zd failed, no address space\n",
342 alloc->pid, size);
343 pr_err("allocated: %zd (num: %zd largest: %zd), free: %zd (num: %zd largest: %zd)\n",
344 total_alloc_size, allocated_buffers, largest_alloc_size,
345 total_free_size, free_buffers, largest_free_size);
346 eret = ERR_PTR(-ENOSPC);
347 goto error_unlock;
348 }
总之,即使应用程序进程没有终止,也可以抛出deadobjectexception。
根本原因很可能是因为应用的粘合剂缓冲液已满,不会影响系统。
因此,我认为在BroadcastQueue中捕捉到DeadObjectException后不必使应用程序崩溃。