RuntimeException: Package manager has died
原文出处:http://blog.csdn.net/xxooyc/article/details/50162523,(部分修改)
bug描述
W/System.err: java.lang.RuntimeException: Package manager has died
W/System.err: at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:122)
W/System.err: at com.qq.googleplay.common.utils.AppUtil.isInstalled(AppUtil.java:73)
W/System.err: at com.qq.googleplay.manager.DownloadManager.getDownLoadInfo(DownloadManager.java:182)
W/System.err: at com.qq.googleplay.ui.fragment.HomeFragment$HomeAdapter$1.run(HomeFragment.java:179)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err: at java.lang.Thread.run(Thread.java:818)
出现bug的代码
/*** 判断包是否安装** @param context* @param packageName* @return*/public static boolean isInstalled(Context context, String packageName) {PackageManager manager = context.getPackageManager();try {manager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);return true;} catch (PackageManager.NameNotFoundException e) {return false;}}
bug分析
frameworks/base/core/java/Android/app/ApplicationPackageManager.java
@Override
public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { try { PackageInfo pi = mPM.getPackageInfo(packageName, flags, mContext.getUserId()); if (pi != null) { return pi; } } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } throw new NameNotFoundException(packageName);
}
这是一个Binder调用,造成这个的原因是因为发生了RemoteException
Caused by: android.os.TransactionTooLargeException
W/System.err: Caused by: android.os.TransactionTooLargeException
W/System.err: at android.os.BinderProxy.transactNative(Native Method)
W/System.err: at android.os.BinderProxy.transact(Binder.java:507)
W/System.err: at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:1806)
W/System.err: at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:117)
frameworks/base/core/jni/android_util_Binder.cpp
case FAILED_TRANSACTION:
ALOGE("!!! FAILED BINDER TRANSACTION !!!");
// TransactionTooLargeException is a checked exception, only throw from certain methods.
// FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
// but it is not the only one. The Binder driver can return BR_FAILED_REPLY
// for other reasons also, such as if the transaction is malformed or
// refers to an FD that has been closed. We should change the driver
// to enable us to distinguish these cases in the future.
jniThrowException(env, canThrowRemoteException ? "android/os/TransactionTooLargeException" : "java/lang/RuntimeException", NULL);
break;
可以看出如果Binder的使用超出了一个进程的限制就会抛出TransactionTooLargeException这个异常。如果是其他原因造成Binder crash的话就会抛出RuntimeException。
那一个进程的Binder内存限制是多少?
frameworks/native/libs/binder/ProcessState.cpp:
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
这便是一个进程中binder的大小,大约1M。
给Binder分配内存的代码:
#if !defined(HAVE_WIN32_IPC)
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) { // *sigh* ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n"); close(mDriverFD); mDriverFD = -1;
}
通过上面的清理,知道了如果一个进程中使用的Binder内容超过了1M,就会crash.
而如果这时候恰巧在用getPackageManager()做事情,就会提示Package manager has died
可以事实真的是这样的吗?
写了个demo来证明一下
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); test(); } private void test() { for (int i = 0; i < 2; i++) { new Thread() { @Override public void run() { int count = 0; List<PackageInfo> list = getPackageManager() .getInstalledPackages(10000); for (PackageInfo info : list) { if(count >=1000){ break; } try { PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES); Log.e("yanchen", "yanchen threadid:"+Thread.currentThread().getId() + ",i:" + count++); } catch (NameNotFoundException e) { } } } }.start(); } }
}
这个Demo就是同时创建两个线程来进行Binder调用
运行打印的log
E/yanchen (21180): yanchen threadid:4097,i:271
E/yanchen (21180): yanchen threadid:4097,i:272
E/yanchen (21180): yanchen threadid:4097,i:273
E/yanchen (21180): yanchen threadid:4097,i:274
E/yanchen (21180): yanchen threadid:4097,i:275
E/yanchen (21180): yanchen threadid:4097,i:276
此时也如预期发生了Crash:
E/JavaBinder(31244): !!! FAILED BINDER TRANSACTION !!!
E/AndroidRuntime(31244): FATAL EXCEPTION: Thread-4798
E/AndroidRuntime(31244): Process: com.example.testdl, PID: 31244
E/AndroidRuntime(31244): java.lang.RuntimeException: Package manager has died
E/AndroidRuntime(31244): at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:155)
E/AndroidRuntime(31244): at com.example.testdl.MainActivity$1.run(MainActivity.java:40)
E/AndroidRuntime(31244): Caused by: android.os.TransactionTooLargeException
E/AndroidRuntime(31244): at android.os.BinderProxy.transactNative(Native Method)
E/AndroidRuntime(31244): at android.os.BinderProxy.transact(Binder.java:496)
E/AndroidRuntime(31244): at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:2208)
E/AndroidRuntime(31244): at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:150)
E/AndroidRuntime(31244): ... 1 more
D/EnterpriseDeviceManagerService( 3021): isMana
解决方式
其实只要避免多个线程同时来调用Binder就可以了,毕竟一个线程用了会释放,所以理论上是很难发生的。
修改后的Demo
synchronized(MainActivity.class){ PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName,PackageManager.GET_ACTIVITIES);
}
再次运行就不会Crash了
RuntimeException: Package manager has died相关推荐
- [Android Pro] 分析 Package manager has died
reference to : http://blog.csdn.net/xxooyc/article/details/50162523 这是今天遇到的一个issue,由于Binder造成的.虽然比较简 ...
- Guidance Package Manager button doesn’t appear in the VS menu
Problem: After installing Enterprise Library 3.1 – May 2007, when I open vs.net, there is no Guidanc ...
- Swift Package Manager 库制作
Swift Package Manager 是苹果官方推出的库管理工具.类似 cocoapods. 准备事项: 一个需要封装的库 存放库的远程仓库,如 github.gitee.gitLab等 创建P ...
- Error: Could not access the Package Manager. Is the system running?
最近在搭建cordova,android 开发环境,安装android studio之后创建一个demo之后,运行想看一下效果,在运行过程中创建一个虚拟机(arm)的,等了有1分钟左右,再次运行程序, ...
- 在linux上安装cuda的时候报错:Existing package manager installation of the driver found.
文章目录: 1 错误原因 2 解决方法 1 错误原因 安装cuda的时候提示有多个显卡驱动:Existing package manager installation of the driver fo ...
- RPM是RedHat Package Manager(RedHat软件包管理工具)类似Windows里面的“添加/删除程序”...
rpm 执行安装包 二进制包(Binary)以及源代码包(Source)两种.二进制包可以直接安装在计算机中,而源代码包将会由RPM自动编译.安装.源代码包经常以src.rpm作为后缀名. 常用命令组 ...
- 在Synaptic Package Manager 加载USB 接口的CD-ROM
1因为Synaptic Package Manager 会去根目录下查找文件夹/cdrom, 但是新的Ubuntu 会把USB CDROM(/dev/sr0) mount 到 /media/Ubunt ...
- Package Manager Console 向VS2010安装 EntityFramework
尝试用VS2010--工具--Library Package Manager--Add Library Package Reference的online搜索 EntityFramework, 再找到的 ...
- Unity Package Manager Error的解决方案
问题来源 启动Unity时显示 fail to start Unity Package Manager,软件环境为 Unity 2017.3.0f3. 解决方案 根据网上所给的方案,我选择添加环境变量 ...
最新文章
- 分不清的InputStream和OutputStream
- 白炽灯可控硅调光程序
- mxnet基础到提高(38)-自动梯度计算
- 如何将SAP云平台Neo环境的Subaccount注册到IAS服务里
- linux c语 curl代码_偷懒必备工具——一键生成爬虫代码
- 云原生时代|分布式系统设计知识图谱(内含22个知识点)
- 2018前端学习总结
- Qt4_坐标系统变换
- 蓝桥杯官网题库【简单题解析】持续更新
- 中医针灸学综合练习题库【10】
- Completed 406 NOT_ACCEPTABLE
- 微信小程序 获取用户手机屏幕高度与宽度
- 【新知实验室】TRTC视频会议
- 如何将PPT进行压缩?简单的方法介绍
- Windows程序设计最新书籍教程
- cpu是几核的怎么查看
- Web前端--HTML+CSS+JS实现圣诞抓礼物小游戏
- 计算机图形学学习记录 系统及图形硬件
- 三十学艺与 Linux Networking Cookbook
- 基于Matlab生成并可视化多架飞机轨迹仿真(附源码)