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类中,当它通过Binder调用scheduleRegisteredReceiver时,DeadObjectException抛出。就像LOG说的那样:小包裹上的交易失败;远程进程可能已经死了,但是为什么RuntimeException会抛出com.android.systemui进程,如果它已经死了?
答案 0 :(得分:5)
我终于找到了根本原因,它发生在绑定器内核中。
目前,我发现可能导致在BroadcastQueue中抛出DeadObjectException的两个原因以及应用程序中ActivityThread中的RemoteServiceException:
相关代码如下所示:
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 }
因此,这不会“最终破坏系统稳定性”。它只会影响应用程序本身。
可以通过以下步骤触发错误:
以下是代码:
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后没有必要使应用程序崩溃。
答案 1 :(得分:0)
基本上,艾克(Rick Ai)对自己的问题的回答都是正确的,但这是一个真实的例子:
如果您的应用创建并注册了一大堆BroadcastReceiver
实例,所有实例都在监听相同的操作(可能是由于应用中的泄漏或错误所致),那么系统进程中的ActivityManagerService将调用{{每个已注册实例的1}}方法android.app.IApplicationThread
。注意,此特定方法的活页夹事务为scheduleRegisteredReceiver
。由于它是oneway
,因此每次调用将立即返回,并且对绑定程序驱动程序的调用将在每个事务完成之前非常迅速地发生,从而有效地并行运行它们。
假设您的应用程序中有100个接收器,接收到的广播包含20 KiB数据。现在,您有2个MiB试图通过活页夹驱动程序,它将失败due to the limit of 1 MiB。
在内核日志中,您将看到:
oneway
因此,请注意泄漏binder: 1282:1298 transaction failed 29201/-28, size 28052-8 line 3072
并注意BroadcastReceiver
活页夹交易。请注意,显然AIDL文件可能未声明方法oneway
,但如果AIDL编译器认为有可能,它可能会以这种方式结束。