android.os.TransactionTooLargeException异常

来源:互联网 发布:周年庆h5源码 编辑:程序博客网 时间:2024/05/16 14:46
一. 背景

输入法在V2.30(185)和V2.35(196)两个版本中都碰到了大量的TransactionTooLargeException的崩溃问题,其中崩溃的堆栈有所不同:

  • V2.30:android.app.ApplicationPackageManager.getInstalledPackages(ApplicationPackageManager.java:464)
  • V2.35:android.view.inputmethod.InputMethodManager.getEnabledInputMethodList(InputMethodManager.java:602)

最终通过查找代码中的改动点,发现其中的原因就是:多个线程同时调用了以下的接口:
  • List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
  • List<RunningTaskInfo> tasksInfo = activityManager.getRunningTasks(1);
  • List<PackageInfo> appInfoList = pkgManager.getInstalledPackages(0);  
那么为什么调用这些接口会出现这个异常呢,我们从异常出现的原因为出发点进行讲解。

二. TransactionTooLargeException的原因

从android的开发文档(http://developer.android.com/reference/android/os/TransactionTooLargeException.html)中我们了解到该异常的描述:   
     因为Binder太大了导致传输失败。
     当调用远程(跨进程)方法时,方法所带的参数以及返回值多会以parcel对象保存在Binder传输缓冲区进行传输的。如果参数或者返回值所占的内存超过传输缓冲区,调用将会失败同时会抛出TransactionTooLargeException异常。
     Binder传输缓冲区是同一进程中所有传输操作所共享的,大小为1Mb。因此当进程中同一时刻,如果有大量的跨进程方法调用时,就要注意了。
从以上异常的描述,可以总结出现该异常的原因:
  • 跨进程方法调用
  • 调用的方法带的参数或者返回值占用较多内存
  • 同一时刻方法调用次数太多

三. 输入法为何出现TransactionTooLargeException

 从TransactionTooLargeException出现的原因可知:
  • 跨进程方法调用
     查看android的框架原理机制了解android的框架机制是通过IPC的机制去实现各个服务的管理,所有服务管理对象都是跨进程的调用,如:
     PackageManager,InputMethodManager,ActivityManager都是通过binder传输进行跨进程调用
  • 调用的方法带的参数或者返回值占用较多内存
    获取用户所有安装应用列表,如果用户安装大量应用的情况下,数据量还是比较大
  • 同一时刻方法调用次数太多
     输入法启动时会调用2次getInstalledPackages,广告sdk智能预加载每隔10s会调用一次getRunningAppProcesses或者getRunningTasks,调用5-6次getInstalledPackages

四. 如何避免

   了解问题出现的条件后,该问题就迎刃而解,同时在项目开发过程中就需要避免问题的发生,整理的方法如下:
  •   跨进程方法调用时尽量减少参数或者返回值的内存占用
          如:getInstalledPackages使用过滤参数减少返回结果的内存占用
  •  不要多个线程同时调用跨进程方法,尽量减少调用次数或者重复利用调用的结果 
          如: 整个项目中共用一份安装列表,减少getInstalledPackages的调用次数; 如果同一时刻需要调用getInstalledPackages,getRunningAppProcesses,getRunningTasks等方法,请使用同一个线程进行操作
阅读全文
0 0
原创粉丝点击