FATAL EXCEPTION IN SYSTEM PROCESS:java.lang.NullPointerException 之monkey

本文介绍了一种Android系统中出现Unknownbindererrorcode0xfffffff7错误的情况及其解决办法,并通过修改ActivityManagerService源代码解决了Monkey工具启动失败的问题。


case1

 Unknown binder error code 0xfffffff7 出现的原因。

             

                当客户端与服务端正在通过Binder机制交互时,例如A正在通过Binder机制与B对象进行交互,即A请求B do something,

       这个过程中如果Binder机制发生了异常,导致A与B的交互不能正常进行,例如代码中显示调用System.exit(0)结束应用程序

        (说明:System.exit(0)方法会 清空该Process的一切资源,包括Activity、Service、BroadcastReceiver等资源,Binder交互

      也结束),系统就打印如下Log信息:“Error: JavaBinder  Unknown binder error code. 0xfffffff7”。接下来,C++层会调用

       binderDied() 法,其Binder客户端也死掉了,





case2


测试组使用Monkey在 Android上想对APK进行自动化测试,但在启动Monkey测试工具时,一直无法正常启动,
1. shell@android:/ $ monkey -p com.android.calculator2 -v 100
2. monkey -p com.android.calculator2 -v 100
3. :Monkey: seed=1393356259515 count=100
4. :AllowPackage: com.android.calculator2
5. :IncludeCategory: android.intent.category.LAUNCHER
6. :IncludeCategory: android.intent.category.MONKEY
7. Killed

一执行就会被killed,无意间测试说起这个问题,说是因为这个系统我们定制过,应该是定制的原因导致的问题。

我较真了,怎么可能是我们定制的原因呢?一般的APK在这个系统上都是可以正常运行的,并且也没有出过问题,所以我对定制这个说法完全不认同。

让相关人员重新执行后,让他同时提供相应的logcat的日志。

日志如下:

01. 02-13 10:02:24.604 D/<a href="http://www.it165.net/pro/ydad/" target="_blank" class="keylink">Android</a>Runtime(14430): Calling main entry com.android.commands.monkey.Monkey
02. 02-13 10:02:24.614 D/dalvikvm(14430): Note: class Landroid/app/ActivityManagerNative; has 168 unimplemented (abstract) methods
03. 02-13 10:02:24.614 D/AndroidRuntime(14430): Shutting down VM
04. 02-13 10:02:24.614 W/dalvikvm(14430): threadid=1: thread exiting with uncaught exception (group=0x416a5700)
05. 02-13 10:02:24.614 E/ActivityManager(  605): Activity Manager Crash
06. 02-13 10:02:24.614 E/ActivityManager(  605): java.lang.NullPointerException
07. 02-13 10:02:24.614 E/ActivityManager(  605):     at com.android.server.am.ActivityManagerService.registerReceiver(ActivityManagerService.java:11867)
08. 02-13 10:02:24.614 E/ActivityManager(  605):     at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:308)
09. 02-13 10:02:24.614 E/ActivityManager(  605):     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:1809)
10. 02-13 10:02:24.614 E/ActivityManager(  605):     at android.os.Binder.execTransact(Binder.java:388)
11. 02-13 10:02:24.614 E/ActivityManager(  605):     at dalvik.system.NativeStart.run(Native Method)
12. 02-13 10:02:24.624 E/JavaBinder(14430): Unknown binder error code. 0xfffffff7
13. 02-13 10:02:24.624 I/Process (14430): Sending signal. PID: 14430 SIG: 9
14. 02-13 10:02:24.624 E/AndroidRuntime(14430): *** FATAL EXCEPTION IN SYSTEM PROCESS: main
15. 02-13 10:02:24.624 E/AndroidRuntime(14430): java.lang.NullPointerException
16. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at android.os.Parcel.readException(Parcel.java:1437)
17. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at android.os.Parcel.readException(Parcel.java:1385)
18. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at android.app.ActivityManagerProxy.registerReceiver(ActivityManagerNative.java:2237)
19. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.commands.monkey.MonkeyNetworkMonitor.register(MonkeyNetworkMonitor.java:88)
20. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.commands.monkey.Monkey.getSystemInterfaces(Monkey.java:979)
21. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.commands.monkey.Monkey.run(Monkey.java:586)
22. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.commands.monkey.Monkey.main(Monkey.java:509)
23. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
24. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:235)
25. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at dalvik.system.NativeStart.main(Native Method)
26. 02-13 10:02:24.624 E/AndroidRuntime(14430): Error reporting crash
27. 02-13 10:02:24.624 E/AndroidRuntime(14430): android.os.RemoteException: Unknown binder error code. 0xfffffff7
28. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at android.os.BinderProxy.transact(Native Method)
29. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:3525)
30. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:76)
31. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
32. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
33. 02-13 10:02:24.624 E/AndroidRuntime(14430):     at dalvik.system.NativeStart.main(Native Method)

我了个去,这个程序一运行,居然把 Activity Manager 给搞挂了,从现象来看,应该是Framework层的bug,即使应用有问题,ActivityManger也不应该挂。

分析了一下代码,看看 com.android.server.am.ActivityManagerService.registerReceiver 的实现:

01. public Intent registerReceiver(IApplicationThread caller, String callerPackage,
02. IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
03. ...
04. synchronized(this) {
05. ProcessRecord callerApp = null;
06. if (caller != null) {
07. callerApp = getRecordForAppLocked(caller);
08. if (callerApp == null) {
09. throw new SecurityException(
10. "Unable to find app for caller " + caller
11. + " (pid=" + Binder.getCallingPid()
12. + ") when registering receiver " + receiver);
13. }
14. ...
15. callingUid = callerApp.info.uid;
16. callingPid = callerApp.pid;
17. } else {
18. callerPackage = null;
19. callingUid = Binder.getCallingUid();
20. callingPid = Binder.getCallingPid();
21. }
22.  
23. ...
24.  
25. BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,   // 日志显示,挂在这里
26. permission, callingUid, userId, callerApp.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
27. ...
28. }

从代码上看,出现空指针异常的这个点,确实是有缺陷的,如果 caller 为null,则 callerApp 就是 null。

Google发布的代码,也会有bug,是人写的代码,就有缺陷啊。

修改成为如下:

1. BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
2. permission, callingUid, userId,
3. (callerApp != null && (callerApp.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0));

重新编译出相应的 services.jar,替换 /system/framework/ 下的同名文件,再让测试重新验证,问题解决。

<think>我们正在分析一个系统级错误:在Android系统的ConnectivityServiceThread线程中发生了FATAL EXCEPTION,异常信息为`java.lang.RuntimeException: android.os.DeadObjectException`。根据引用[3]的内容,DeadObjectException通常表示跨进程通信(Binder)时,对方进程已经死亡(可能被杀死或崩溃)。在我们的场景中,ConnectivityServiceThread是系统进程中的线程,它可能在尝试与另一个进程通信时遇到了该进程已经死亡的情况。 ### 错误原因分析 1. **Binder通信中断**:`DeadObjectException`发生在Binder调用过程中,当服务端进程已经终止但客户端仍尝试调用其方法时抛出[^3]。 2. **系统服务依赖**:ConnectivityService(负责网络连接管理)可能依赖的其他系统服务(如PackageManagerService)意外崩溃,导致其Binder代理对象失效。 3. **资源限制**:系统资源不足(如Binder事务缓冲区溢出)可能导致通信失败,尤其在低版本Android(6.0及以下)中更常见[^3]。 ### 解决方案 #### 1. 检查依赖服务状态 确保ConnectivityService所依赖的关键服务(如PackageManagerService、ActivityManagerService)正常运行。在系统日志中搜索以下关键信息: ```logcat E ActivityManager: Service serviceName has died ``` 若发现服务频繁重启,需进一步分析其崩溃原因。 #### 2. 优化Binder通信 针对低版本Android(<=6.0)的Binder缓冲区限制: - **减少传输数据量**:避免在Binder调用中传递大型对象(如大数组、Bitmap)。若必须传递,采用分块传输机制。 - **使用PARCELABLE_ELIDE_DUPLICATES标志**:Android 7.0+引入该标志可自动消除Parcelable对象的重复数据,若需兼容低版本,可手动实现数据精简[^3]。 #### 3. 添加异常处理 在ConnectivityService的Binder调用处捕获`DeadObjectException`并进行恢复操作: ```java try { // 执行跨进程调用 someRemoteService.method(); } catch (DeadObjectException e) { // 重新绑定服务或清理状态 reconnectService(); } ``` #### 4. 监控资源使用 - **Binder事务缓冲区**:通过`/proc/[pid]/limits`检查进程的Binder缓冲区大小,若频繁接近上限(通常1MB),需优化调用频率。 - **内存压力**:使用`dumpsys meminfo`监控系统内存,避免因OOM导致服务终止。 #### 5. 系统更新与补丁 若问题集中在特定设备(如小米),检查厂商是否提供系统更新: ```shell adb shell getprop ro.build.version.incremental # 获取系统版本号 ``` ### 验证步骤 1. 在测试设备上复现问题(通过压力测试网络切换场景)。 2. 部署修复后,监控以下日志确认异常消除: ```logcat ConnectivityService: Binder call to [service] recovered after death ``` ### 根本原因预防 $$ \text{预防策略} = \begin{cases} \text{服务隔离} & \text{关键服务独立进程} \\ \text{心跳检测} & \text{定期检查依赖服务存活} \\ \text{熔断机制} & \text{失败调用快速降级} \end{cases} $$ --- §§相关问题§§ 1. `DeadObjectException` 与 `TransactionTooLargeException` 有何关联? 2. 如何为系统服务设计自动恢复机制? 3. Android 中哪些工具可用于诊断 Binder 通信问题? </think>### `ConnectivityServiceThread` 出现 `DeadObjectException` 解决方案分析 **根本原因**:该错误表明系统核心服务 `ConnectivityService` 在跨进程通信(Binder)时,目标进程已崩溃或终止,导致通信链路中断。常见触发场景包括: 1. **Binder缓冲区溢出**:低版本 Android(≤6.0)的 Binder 事务缓冲区限制为 1MB,传输大数据(如 `PackageInfo`)时可能溢出[^3] 2. **依赖服务崩溃**:`ConnectivityService` 依赖的其他系统服务(如 `PackageManagerService`)意外终止 3. **资源竞争**:多线程并发访问系统服务时发生死锁或资源争用 --- ### 分步解决方案 #### 1. **排查 Binder 数据传输问题**(针对低版本 Android) ```java // 示例:精简跨进程传输的数据结构 Bundle params = new Bundle(); // 避免传输大型对象(如 Bitmap) params.putString("key", compressLargeData(originalData)); // Android 7.0+ 使用缓冲区优化标志 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { params.putParcelable("optimized", parcelableObj, PARCELABLE_ELIDE_DUPLICATES); } ``` - **关键措施**: - 检查传输数据是否超过 1MB(使用 `Bundle#getSize()` 验证) - 升级目标设备到 Android 7.0+ 自动启用 `PARCELABLE_ELIDE_DUPLICATES`[^3] - 对 `PackageInfo` 等大型对象进行字段裁剪 #### 2. **增强系统服务健壮性** ```java // 在关键 Binder 调用处捕获异常 try { mPackageManager.getPackageInfo(packageName, 0); } catch (DeadObjectException e) { Log.e(TAG, "依赖服务终止,启动恢复流程"); reconnectService(); // 重新绑定服务 } ``` - **恢复机制**: 1. 捕获异常后触发服务重启:`ActivityManagerService.restartService()` 2. 设置心跳检测:定期向关键服务发送 `ping` 指令 3. 隔离崩溃影响:通过 `HandlerThread` 隔离关键线程 #### 3. **优化系统资源配置** - **调整 Binder 缓冲区大小**(需 root): ```shell adb shell "echo 2097152 > /proc/sys/kernel/binder_transaction_size" ``` - **监控内存压力**: ```shell adb shell dumpsys meminfo | grep "Binder:" # 检查Binder内存使用 ``` - **缓解资源竞争**: - 使用 `synchronized` 保护共享资源 - 避免在 `ConnectivityServiceThread` 执行耗时操作 #### 4. **厂商特定问题处理**(如小米设备) - **云文件访问问题**:检查云端文件下载状态再访问 ```java if (!isCloudFileDownloaded(uri)) { triggerBackgroundDownload(uri); // 触发异步下载 return; // 避免立即访问 } ``` - **更新厂商系统补丁**:检查是否有针对 `DeadObjectException` 的 OTA 更新 --- ### 验证流程 1. **日志分析**: ```shell adb logcat | grep -E "DeadObjectException|BinderTransactionFailed" ``` 2. **压力测试**: ```shell adb shell am broadcast -a android.net.wifi.STRESS_TEST # 触发网络服务压力测试 ``` 3. **监控工具**: - 使用 `systrace` 跟踪 Binder 事务 - 通过 `dumpsys activity services` 检查服务绑定状态 > **注意**:系统级崩溃通常需要厂商提供补丁。若问题高频出现,建议提交完整日志至 [AOSP Issue Tracker](https://issuetracker.google.com/)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值