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. Pandas DataFrame构造简析

    参考书籍:<利用Python进行数据分析> DataFrame简介: DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值.字符串.布尔值等).Dat ...

  2. Python 2 到 Python 3 的变化

    1: commands 被 subprocess 所取代:举例 Python2中使用getoutput: >>> import commands >>> print ...

  3. 语言模型srilm基本用法

    目录: 一基本训练 二语言模型打分 三语言模型剪枝 四语言模型合并 五语言模型使用词典限制 一.基本训练 #功能 读取分词后的text文件或者count文件,然后用来输出最后汇总的count文件或者语 ...

  4. Web前端开发最佳实践(3):前端代码和资源的压缩与合并

    一般在网站发布时,会压缩前端HTML.CSS.JavaScript代码及用到的资源文件(主要是图片文件),目的是加快文件在网络中的传输,让网页更快的展现.当然,CDN分发.缓存等方式也是加快代码或资源 ...

  5. Docker CentOS 网段与公司网段冲突

    参考文章: <Docker修改默认地址172.17.0.1> 在公司内网的一个虚拟服务器(CentOS 7)安装Docker后,发现网段172.18.0.1和172.17.0.1与公司内部 ...

  6. VS code配置docker的shell环境

    今天尝试了下使用docker来做虚拟机,几番折腾后终于搞定可以用了,但是想着每次都要在命令行敲半天也太恶心了,所以就找了一下可视化的管理工具 首先说下,我的docker主机环境是windows10,用 ...

  7. 【C++初级】static用法总结、问题探讨及常见错误排查

    static的基本用法: static的作用主要有两种第一个作用是限定作用域:第二个作用是保持变量内容持久化: 一.c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字sta ...

  8. SpringMVC框架 注解 (转)

    原文地址:http://www.cnblogs.com/yjq520/p/6734422.html 1.@Controller @Controller 用于标记在一个类上,使用它标记的类就是一个Spr ...

  9. 2017/11/3 Leetcode 日记

    2017/11/3 Leetcode 日记 654. Maximum Binary Tree Given an integer array with no duplicates. A maximum ...

  10. Sea Battle<海战>(思路题)

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...