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

解决Unknownbindererrorcode0xfffffff7
本文介绍了一种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应用中的空指针异常(NullPointerException),具体错误信息是: java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.List.clear()' on a null object reference 这个错误发生在主线程(FATAL EXCEPTION: main),导致应用崩溃。错误信息表明我们试图在一个为null的List对象上调用clear()方法。 ### 错误原因分析 根据引用[2]中的经验,空指针异常通常是因为对象未初始化就被使用。此处我们尝试调用一个List接口的方法(clear()),而该List对象实际上是null。可能的原因包括: 1. **未初始化集合对象**:在使用List之前,没有对其进行初始化(例如,没有执行`list = new ArrayList<>();`)。 2. **初始化时机不当**:可能在初始化之前就调用了clear()方法。 3. **对象被意外置为null**:可能在某个地方将List对象置为了null,或者在异步操作中未正确初始化。 ### 解决方案 #### 1. 确保在使用List之前已经初始化 在调用任何List方法(包括clear())之前,必须确保该List不是null。例如: ```java // 错误示例 private List<String> mDataList; // 声明但未初始化 public void clearData() { mDataList.clear(); // 此时mDataList为null,会抛出NullPointerException } ``` 修正为: ```java private List<String> mDataList = new ArrayList<>(); // 初始化 public void clearData() { mDataList.clear(); // 安全 } ``` #### 2. 检查对象是否为空 在调用方法前进行空检查: ```java public void clearData() { if (mDataList != null) { mDataList.clear(); } } ``` #### 3. 检查初始化流程 如果List是在其他地方(如onCreate())初始化的,确保初始化代码被执行。例如,在Activity中: ```java @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 确保初始化 mDataList = new ArrayList<>(); } ``` ### 实际场景分析 根据错误信息`java.util.List.clear()`,我们通常会在以下场景使用clear()方法: - 刷新数据:在重新加载数据前清空旧数据。 - 重置状态:在界面重置时清空列表。 ### 预防措施 1. **使用@NonNull注解**:在Android Studio中,可以使用注解来标记非空字段: ```java @NonNull private List<String> mDataList = new ArrayList<>(); ``` 2. **使用静态代码分析工具**:如Lint,可以检测出可能为null的引用。 3. **使用Kotlin**:Kotlin语言有非空类型,可以在编译时避免空指针异常。 ### 类似问题参考 - 引用[1]:在LoginActivity中,因为Button对象为null,调用setOnClickListener导致空指针。解决方案是检查布局文件中Button的id是否匹配,以及是否正确使用findViewById。 - 引用[3]:EditText或TextView为null时调用方法也会导致空指针。解决方案同上,确保视图已经正确初始化。 ### 总结 当遇到`Attempt to invoke interface method ... on a null object reference`时,核心问题是**对象未初始化**。请按照以下步骤解决: 1. 找到使用clear()方法的代码行(通过堆栈跟踪定位)。 2. 检查该List对象是否初始化。 3. 如果初始化在别处,确保初始化代码在调用该方法之前执行。 4. 添加空指针检查。 通过以上步骤,应该可以解决这个空指针异常问题。 --- ### 相关问题 1. 如何避免Android应用中的空指针异常? 2.Android开发中,有哪些常见的对象未初始化场景? 3. 如何通过代码设计减少空指针异常? 4. 使用Kotlin开发如何避免空指针?</think>### Android 空指针异常分析:`java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.List.clear()' on a null object reference` #### 错误原因分析 1. **未初始化的集合对象** 尝试在未初始化的 `List` 对象上调用 `clear()` 方法,此时对象为 `null`: ```java // 错误示例 List<String> dataList; // 仅声明未初始化 dataList.clear(); // 触发NullPointerException ``` 2. **异步初始化失败** 集合可能在异步线程中初始化(如网络请求回调),但后续操作在主线程提前调用: ```mermaid graph LR A[主线程调用 clear] --> B{List是否初始化?} B -->|未初始化| C[NullPointerException] B -->|已初始化| D[正常执行] ``` 3. **生命周期管理不当** Activity/Fragment销毁时未释放资源,重建后引用旧对象: ```java // 错误场景 public class MyActivity extends Activity { private List<String> cache; // 在配置变更后可能为null void onRefresh() { cache.clear(); // 旋转屏幕后触发崩溃 } } ``` #### 解决方案 **1. 初始化检查(推荐)** ```java // 安全调用示例 if (myList != null) { myList.clear(); } else { // 可选:初始化或记录日志 myList = new ArrayList<>(); Log.w("TAG", "List was null, initialized new instance"); } ``` **2. 防御性初始化** ```java // 在声明时或构造函数中初始化 private List<String> data = new ArrayList<>(); // 或在首次使用前初始化 public void clearData() { if (data == null) { data = new ArrayList<>(); } data.clear(); } ``` **3. 使用空对象模式** ```java // 避免返回null的集合 public List<String> getSafeList() { return (myList != null) ? myList : Collections.emptyList(); } // 调用方式 getSafeList().clear(); // 对emptyList调用clear是安全的 ``` **4. 生命周期管理** ```java // 在Activity/Fragment中正确管理资源 @Override protected void onDestroy() { super.onDestroy(); myList = null; // 显式释放引用 } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 确保重新初始化 if (myList == null) { myList = new ArrayList<>(); } } ``` #### 调试技巧 1. **定位崩溃点** 通过堆栈跟踪找到调用 `clear()` 的具体代码行: ``` FATAL EXCEPTION: main Process com.example.gobangapplication ... at com.example.gobangapplication.GameActivity.resetBoard(GameActivity.java:127) <-- 关键行 ``` 2. **空安全检查工具** ```java // 使用Android Studio的@Nullable/@NonNull注解 public void updateList(@NonNull List<String> data) { Objects.requireNonNull(data); // 显式检查 data.clear(); } ``` 3. **日志诊断** ```java Log.d("ListState", "List is " + (myList == null ? "null" : "valid")); ``` #### 预防措施 - **编码规范**:所有集合对象在声明时立即初始化 - **静态分析**:启用Lint检查的`NullSafe`选项 - **架构优化**:使用ViewModel管理数据,避免生命周期问题 - **单元测试**:添加空对象边界测试用例 ```java @Test public void testClearWithNullList() { GameLogic logic = new GameLogic(); logic.setDataList(null); logic.clearData(); // 应安全处理null } ``` > **关键提示**:在Android开发中,**配置变更(如屏幕旋转)** 是导致空引用的常见原因,使用`ViewModel`+`LiveData`可有效解决[^1][^2]。 --- ### 相关问题 1. 如何在Android中安全处理可能为null的集合返回值? 2. ViewModel如何帮助避免空指针异常? 3. 有哪些适用于Android的静态代码分析工具可以检测空指针风险? 4. Kotlin的空安全特性如何解决这类问题? 5. 在RecyclerView适配器中如何处理空数据集?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值