1.异常Log Pattern
BroadcastQueue: Can't deliver broadcast to com.my.app (pid 8047). Crashing it.
ActivityManager: Killing 8047:com.my.demo/1000 (adj 0): scheduleCrash for 'can't deliver broadcast' failed
BroadcastQueue: Failure sending broadcast Intent { act=android.intent.action.BATTERY_CHANGED flg=0x60000010 (has extras) }
BroadcastQueue: android.os.DeadObjectException: Transaction failed on small parcel; remote process probably died
BroadcastQueue: at android.os.BinderProxy.transactNative(Native Method)
BroadcastQueue: at android.os.BinderProxy.transact(Binder.java:764)
BroadcastQueue: at android.app.IApplicationThread$Stub$Proxy.scheduleRegisteredReceiver(IApplicationThread.java:1560)
BroadcastQueue: at com.android.server.am.BroadcastQueue.performReceiveLocked(BroadcastQueue.java:491)
BroadcastQueue: at com.android.server.am.BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastQueue.java:703)
BroadcastQueue: at com.android.server.am.BroadcastQueue.processNextBroadcast(BroadcastQueue.java:858)
BroadcastQueue: at com.android.server.am.BroadcastQueue$BroadcastHandler.handleMessage(BroadcastQueue.java:171)
BroadcastQueue: at android.os.Handler.dispatchMessage(Handler.java:106)
BroadcastQueue: at android.os.Looper.loop(Looper.java:164)
BroadcastQueue: at android.os.HandlerThread.run(HandlerThread.java:65)
BroadcastQueue: at com.android.server.ServiceThread.run(ServiceThread.java:46)
2.Crash的过程
出现两种情况
1.data parcel size大于2m 200×1024
2.异常 主要两种 deadobjectexception 调用的进程死掉了
另外为其他异常
@frameworks/base/core/jni/android_util_Binder.cpp
void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
bool canThrowRemoteException, int parcelSize)
case FAILED_TRANSACTION: {
ALOGE("!!! FAILED BINDER TRANSACTION !!! (parcel size = %d)", parcelSize);
if (canThrowRemoteException && parcelSize > 200*1024) {
// bona fide large payload
exceptionToThrow = "android/os/TransactionTooLargeException";
snprintf(msg, sizeof(msg)-1, "data parcel size %d bytes", parcelSize);
} else {
// Heuristic: a payload smaller than this threshold "shouldn't" be too
// big, so it's probably some other, more subtle problem. In practice
// it seems to always mean that the remote process died while the binder
// transaction was already in flight.
exceptionToThrow = (canThrowRemoteException)
? "android/os/DeadObjectException"
: "java/lang/RuntimeException";
snprintf(msg, sizeof(msg)-1,
"Transaction failed on small parcel; remote process probably died");
}
jniThrowException(env, exceptionToThrow, msg);
} break;
//performReceiveLocked报错并且crash app
@BroadcastQueue.java
482 void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
483 Intent intent, int resultCode, String data, Bundle extras,
484 boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
485 // Send the intent to the receiver asynchronously using one-way binder calls.
486 if (app != null) {
487 if (app.thread != null) {
488 // If we have an app thread, do the call through that so it is
489 // correctly ordered with other one-way calls.
490 try {
491 app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
492 data, extras, ordered, sticky, sendingUser, app.repProcState);
493 // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
494 // DeadObjectException when the process isn't actually dead.
495 //} catch (DeadObjectException ex) {
496 // Failed to call into the process. It's dying so just let it die and move on.
497 // throw ex;
498 } catch (RemoteException ex) {
499 // Failed to call into the process. It's either dying or wedged. Kill it gently.
500 synchronized (mService) {
501 Slog.w(TAG, "Can't deliver broadcast to " + app.processName
502 + " (pid " + app.pid + "). Crashing it."); //here
503 app.scheduleCrash("can't deliver broadcast"); //crash app
504 }
505 throw ex;
506 }
507 } else {
508 // Application has died. Receiver doesn't exist.
509 throw new RemoteException("app.thread must not be null");
510 }
511 } else {
512 receiver.performReceive(intent, resultCode, data, extras, ordered,
513 sticky, sendingUser);
514 }
515 }
@frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
void scheduleCrash(String message) {
// Checking killedbyAm should keep it from showing the crash dialog if the process
// was already dead for a good / normal reason.
if (!killedByAm) {
if (thread != null) {
if (pid == Process.myPid()) {
Slog.w(TAG, "scheduleCrash: trying to crash system process!");
return;
}
long ident = Binder.clearCallingIdentity();
try {
thread.scheduleCrash(message); //throw RemoteServiceException然后kill
} catch (RemoteException e) {
// If it's already dead our work is done. If it's wedged just kill it.
// We won't get the crash dialog or the error reporting.
kill("scheduleCrash for '" + message + "' failed", true);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
}
void kill(String reason, boolean noisy) {
if (!killedByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (noisy) {
Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
}
EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
Process.killProcessQuiet(pid);
ActivityManagerService.killProcessGroup(uid, pid);
if (!persistent) {
killed = true;
killedByAm = true;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
@frameworks/base/core/java/android/app/ActivityThread.java
public void scheduleCrash(String msg) {
sendMessage(H.SCHEDULE_CRASH, msg);
}
1767 case SCHEDULE_CRASH:
1768 throw new RemoteServiceException((String)msg.obj);
3.Binder错误信息kernel log
@binder.c
4067err_alloc_t_failed:
4068err_bad_call_stack:
4069err_empty_call_stack:
4070err_dead_binder:
4071err_invalid_target_handle:
...
4081 binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
4082 "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n",
4083 proc->pid, thread->pid, return_error, return_error_param,
4084 (u64)tr->data_size, (u64)tr->offsets_size,
4085 return_error_line);
11-25 09:31:23.786059 1052 1052 I [128416.232769](6)[1052:ActivityManager]binder: 1025:1052 transaction failed 29201/-28, size 792-8 line 3781
那么问题来了,这个过程也是使用binder.
同样是systemserver向应用发送,为什么之前不成功,现在可以了,因为当时空间不够,后面可能够了
return_error --> 29201 --> BR_FAILED_REPLY
return_error_param --> 28 --> ENOSPC /* No space left on device */
31#define ENOSPC 28 /* No space left on device */
还有些错是parcel太大导致,这里是没有空间,可能注册广播太多,注销慢,或者逻辑错误,也可能是进程死了
还可以可能比如systemserver的线程都在做数据库之类的blocked
4.其他例子
https://ask.csdn.net/questions/682317
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 3625220 bytes
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3982)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: android.os.TransactionTooLargeException: data parcel size 3625220 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:617)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3632)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3974)