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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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应用崩溃的问题,具体错误是FATAL EXCEPTION: main,并带有NullPointerException。用户希望了解这个错误的原因以及如何解决。首先,我需要回忆一下Android开发中常见的NullPointerException的情况。 首先,错误信息显示在尝试调用UserInfo对象的getPassword()方法时发生了空指针异常。这说明某个地方的UserInfo对象是null,而代码没有做空检查就直接调用了它的方法。接下来,我需要分析可能的原因,并考虑如何指导用户排查问题。 可能的第一个原因是UserInfo对象未被正确初始化。例如,从Intent获取数据时可能没有传递UserInfo对象,或者在解析数据时出现了错误。这时候,如果直接调用getPassword()就会抛出NPE。 第二个可能的原因是UserInfo对象在某些情况下没有被正确赋值。例如,从数据库或网络获取数据时可能返回了null,而代码没有处理这种情况。比如,使用Room或Retrofit时,如果查询没有结果或者网络请求失败,可能导致对象为null。 第三个可能的原因是生命周期问题。例如,在Activity或Fragment的onCreate方法中,可能过早地访问还没有初始化的对象。或者在异步回调中,数据还没有返回时就调用了相关方法。 接下来,我需要考虑如何帮助用户定位问题。首先,用户需要找到触发错误的代码位置。根据错误日志中的PID和堆栈跟踪,可以确定崩溃发生的具体位置,比如某个Activity的某一行代码。例如,错误可能出现在MainActivity.java的第42行。 然后,用户需要检查该行代码中涉及UserInfo对象的地方。比如,是否有从Bundle中获取UserInfo对象,或者从其他组件传递过来的数据。例如: UserInfo user = getIntent().getParcelableExtra("user"); String password = user.getPassword(); // 如果user为null,这里就会崩溃 如果这里的user没有被正确传递,就会导致NPE。解决方法是在调用方法前检查对象是否为null: if (user != null) { String password = user.getPassword(); } else { // 处理user为null的情况,比如提示错误或初始化默认值 } 另外,可能是在数据获取的过程中出现了问题,比如数据库查询返回null。这时需要检查数据库操作的代码,确保查询条件正确,并且处理可能的null情况。 还有可能是在异步操作中,比如使用RxJava或LiveData时,回调中未正确处理数据为空的情况。例如: userRepository.getUser().observe(this, user -> { String password = user.getPassword(); // 如果user为null,这里会崩溃 }); 应该改为: userRepository.getUser().observe(this, user -> { if (user != null) { String password = user.getPassword(); } else { // 处理空数据 } }); 此外,代码中可能使用了@Nullable或@NonNull注解,但未遵循这些注解的约定,导致意外的null值。检查这些注解的使用情况也很重要。 总结来说,用户需要做的是: 1. 找到崩溃发生的代码行。 2. 检查相关对象是否可能为null。 3. 添加空检查,确保在调用方法前对象不为null。 4. 处理可能的null情况,避免应用崩溃。 最后,建议用户使用Android Studio的调试工具,在可能的地方设置断点,观察对象的状态,或者使用Log语句输出对象的值,帮助确定哪里出现了null值。此外,启用StrictMode或使用静态代码分析工具如Lint,也能帮助提前发现潜在的空指针问题。</think>这个错误是典型的 **Android空指针异常(NullPointerException)**,具体表现为尝试调用一个`null`对象的方法。以下是逐步分析和解决方案: --- ### **错误分析** ```log FATAL EXCEPTION: main Process: com.example.myexamproject, PID: 7588 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.myexamproject.entity.UserInfo.getPassword()' on a null object reference ``` - **关键信息**:`UserInfo.getPassword()`被调用时,`UserInfo`对象为`null`。 - **根本原因**:代码中直接操作了一个未初始化或未正确赋值的对象。 --- ### **步骤1:定位代码位置** 1. 查看错误日志中的堆栈跟踪(Stack Trace),找到触发异常的代码文件及行号(例如:`MainActivity.java:42`)。 2. 检查该行代码,确认涉及`UserInfo`对象的操作。 --- ### **步骤2:常见原因及排查** #### **原因1:对象未初始化** - **场景**:从`Intent`、`Bundle`、数据库或网络获取`UserInfo`时未正确赋值。 - **示例代码**: ```java UserInfo user = getIntent().getParcelableExtra("user"); String password = user.getPassword(); // user可能为null ``` - **修复方法**:添加空值检查。 ```java if (user != null) { String password = user.getPassword(); } else { // 处理null情况,例如提示错误或赋予默认值 } ``` #### **原因2:异步回调未完成** - **场景**:在网络请求或数据库查询的回调中直接操作对象。 - **示例代码**(使用`LiveData`或`RxJava`): ```java userRepository.getUser().observe(this, user -> { String password = user.getPassword(); // 异步返回的user可能为null }); ``` - **修复方法**:在回调中检查对象有效性。 ```java userRepository.getUser().observe(this, user -> { if (user != null) { String password = user.getPassword(); } else { Log.e("TAG", "User数据为空"); } }); ``` #### **原因3:数据解析失败** - **场景**:JSON反序列化或数据库实体映射错误导致对象为`null`。 - **修复方法**:检查数据解析逻辑,使用`try-catch`捕获异常。 --- ### **步骤3:预防措施** 1. **启用空安全注解**: ```java public class UserInfo { @NonNull private String password; // 标记字段非空 } ``` 2. **使用静态代码分析工具**: - Android Studio 的 `Lint` 检查。 - 第三方工具如 `NullAway` 或 `Kotlin 的可空类型`(推荐迁移到Kotlin)。 3. **防御性编程**: - 在方法入口处检查参数有效性。 - 使用 `Objects.requireNonNull()` 强制非空约束。 --- ### **总结** - **核心问题**:`UserInfo`对象未被正确初始化或赋值。 - **解决步骤**: 1. 定位代码行。 2. 添加空值检查。 3. 处理可能的`null`情况。 - **优化建议**:使用Kotlin(天然支持空安全)或依赖注入框架(如Dagger)管理对象生命周期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值