您的位置:首页 > 移动开发 > Android开发

android.os.TransactionTooLargeException异常

2016-04-07 14:38 585 查看
一. 背景

输入法在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等方法,请使用同一个线程进行操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: