reference to : http://blog.csdn.net/xxooyc/article/details/50162523

这是今天遇到的一个issue,由于Binder造成的。虽然比较简单,还是保持记录下吧。

先来开看一下Crash log:

    E/HpnsService(24810): HPNS Version is 5.0java.lang.RuntimeException: Package manager has died
E/HpnsService(24810): at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:111)
E/HpnsService(24810): at com.xx.xxx.util.AppUtil.checkInstalledPackageVersionCode(AppUtil.java:568)
E/HpnsService(24810): at com.xx.xxx.util.AppUtil.checkAppStatus(AppUtil.java:653)
E/HpnsService(24810): at com.xx.xxx.view.AppListView$LoadingAppThread.run(AppListView.java:723)
E/HpnsService(24810): Caused by: android.os.TransactionTooLargeException
E/HpnsService(24810): at android.os.BinderProxy.transactNative(Native Method)
E/HpnsService(24810): at android.os.BinderProxy.transact(Binder.java:496)
E/HpnsService(24810): at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:1786)
E/HpnsService(24810): at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:106)
E/HpnsService(24810): ... 3 more

为什么会发生Package manager has died?

frameworks/base/core/java/Android/app/ApplicationPackageManager.java:

102    @Override
103 public PackageInfo getPackageInfo(String packageName, int flags)
104 throws NameNotFoundException {
105 try {
106 PackageInfo pi = mPM.getPackageInfo(packageName, flags, mContext.getUserId());
107 if (pi != null) {
108 return pi;
109 }
110 } catch (RemoteException e) {
111 throw new RuntimeException("Package manager has died", e);
112 }
113
114 throw new NameNotFoundException(packageName);
115 }

这是一个Binder调用,造成这个的原因是因为发生了RemoteException。

那为什么友会发生RemoteException?

其实也就是下面的这句Caused by: android.os.TransactionTooLargeException造成的。

为什么会造成TransactionTooLargeException?

frameworks/base/core/jni/android_util_Binder.cpp:

    682        case FAILED_TRANSACTION:
683 ALOGE("!!! FAILED BINDER TRANSACTION !!!");
684 // TransactionTooLargeException is a checked exception, only throw from certain methods.
685 // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
686 // but it is not the only one. The Binder driver can return BR_FAILED_REPLY
687 // for other reasons also, such as if the transaction is malformed or
688 // refers to an FD that has been closed. We should change the driver
689 // to enable us to distinguish these cases in the future.
690 jniThrowException(env, canThrowRemoteException
691 ? "android/os/TransactionTooLargeException"
692 : "java/lang/RuntimeException", NULL);
693 break;

可以看出如果Binder的使用超出了一个进程的限制就会抛出TransactionTooLargeException这个异常。

如果是其他原因造成Binder crash的话就会抛出RuntimeException。

那一个进程的Binder内存限制是多少?

frameworks/native/libs/binder/ProcessState.cpp:

44 #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))

这便是一个进程中binder的大小,大约1M。

给Binder分配内存的代码:

    349#if !defined(HAVE_WIN32_IPC)
350 // mmap the binder, providing a chunk of virtual address space to receive transactions.
351 mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
352 if (mVMStart == MAP_FAILED) {
353 // *sigh*
354 ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
355 close(mDriverFD);
356 mDriverFD = -1;
357 }

通过上面的清理,知道了如果一个进程中使用的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了。

[Android Pro] 分析 Package manager has died的更多相关文章

  1. Package manager has died异常PackageInfo 引发 Crash

    Android 获取 PackageInfo 引发 Crash 填坑 一般 Android 通过PackageInfo这个类来获取应用安装包信息,比如应用内包含的所有Activity名称.应用版本号之 ...

  2. xamarin调试android部署到模拟器错误记录:Deployment failed Mono.AndroidTools.InstallFailedException: Unexpected install output: Error: Could not access the Package Manager. Is the system running?

    问题记录: 1.生成 ok. 2.昨天也是能部署到模拟器的. 但是今天部署的时候就报了这样的一个错误 Deployment failed Mono.AndroidTools.InstallFailed ...

  3. Android 核心分析 之七Service深入分析

    Service深入分析 上一章我们分析了Android IPC架构,知道了Android服务构建的一些基本理念和原理,本章我们将深入分析Android的服务.Android体系架构中三种意义上服务: ...

  4. Android Launcher分析和修改3——Launcher启动和初始化

    前面两篇文章都是写有关Launcher配置文件的修改,代码方面涉及不多,今天开始进入Launcher代码分析. 我们开机启动Launcher,Launcher是由Activity Manager启动的 ...

  5. Cannot find `aapt.exe`. Please install the Android SDK Build-tools package

    Google has updated their SDK tools ("Android SDK Tools" Rev. 23) in a way that also requir ...

  6. Error: Could not access the Package Manager. Is the system running?

    最近在搭建cordova,android 开发环境,安装android studio之后创建一个demo之后,运行想看一下效果,在运行过程中创建一个虚拟机(arm)的,等了有1分钟左右,再次运行程序, ...

  7. [Android Pro] PackageManager#getPackageSizeInfo (hide)

    referce to : http://www.baidufe.com/item/8786bc2e95a042320bef.html 计算Android App所占用d的手机内存(RAM)大小.App ...

  8. Visual Studio 2010 更新NuGet Package Manager出错解决办法

    在Visual Studio 2010的扩展管理器中发现NuGet Package Manger有最新版本更新提示,选择更新安装提示以下错误信息: 2013/4/25 1:11:48 - Micros ...

  9. Android架构分析之使用自定义硬件抽象层(HAL)模块

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 在上一篇博 ...

随机推荐

  1. Adminimize 插件:WordPress根据用户角色显示/隐藏某些后台功能

    倡萌刚才分享了 WordPress根据用户角色隐藏文章/页面的功能模块(Meta Boxes),如果你还想根据不同用户角色显示或隐藏后台的某些功能,比如 顶部工具条.左边导航菜单.小工具.仪表盘.菜单 ...

  2. Java学习(构造方法、this关键字、super应用)

    构 造 方 法 定义:对象创建时使用的方法,即在new一个新对象时,对应构造方法,直接对属性赋值. 语句格式:    修饰符(public 等) 构造方法名(必须跟当前类名一样,否则报错)(参数列表) ...

  3. css写无缝滚动

    html结构: <div class="authority"> <ul> <li> <img src="./images/rep ...

  4. AciveX接口事件的手动实现

    为了理解ActiveX事件的运作原理,特意做了如下实验 初试化过程: try { CLSID clsid; HRESULT hr=::CLSIDFromProgID(L"MSWinsock. ...

  5. Java反序列化漏洞之殇

    ref:https://xz.aliyun.com/t/2043 小结: 3.2.2版本之前的Apache-CommonsCollections存在该漏洞(不只该包)1.漏洞触发场景 在java编写的 ...

  6. 转:[译]CSV 注入:被人低估的巨大风险

    转:https://yq.aliyun.com/articles/225847 原文地址:The Absurdly Underestimated Dangers of CSV Injection 原文 ...

  7. 长沙理工大学第十二届ACM大赛-重现赛 K - 大家一起来数二叉树吧

    题目描述 某一天,Zzq正在上数据结构课.老师在讲台上面讲着二叉树,zzq在下面发着呆. 突然zzq想到一个问题:对于一个n个节点,m个叶子的二叉树,有多少种形态呐?你能告诉他吗? 对于第一组样例的解 ...

  8. JSTL-1

    JSTL的配置和使用: * 配置:将jstl.jar和standard.jar拷贝到WEB-INF/lib下 * 使用:要采用一些指令:采用taglib指令 JSTL标准标签库(JSP Standar ...

  9. cloudstack ssvm 管理地址不够造成无法启动修复过程

    cloudstack日志记录: 上面已经提示了,管理ip没有了,造成这个原因很多,遇到过ssvm非正常关闭就有可能不释放IP慢慢把IP消耗掉.总之这肯定是BUG.按照上面的提示找到对应pod 和dc ...

  10. Socket学习笔记(一)

    1.socket介绍 我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几 ...