0
点赞
收藏
分享

微信扫一扫

android.os.TransactionTooLargeException


一. 背景



输入法在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 条评论