原文出处: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相关推荐

  1. [Android Pro] 分析 Package manager has died

    reference to : http://blog.csdn.net/xxooyc/article/details/50162523 这是今天遇到的一个issue,由于Binder造成的.虽然比较简 ...

  2. 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 ...

  3. Swift Package Manager 库制作

    Swift Package Manager 是苹果官方推出的库管理工具.类似 cocoapods. 准备事项: 一个需要封装的库 存放库的远程仓库,如 github.gitee.gitLab等 创建P ...

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

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

  5. 在linux上安装cuda的时候报错:Existing package manager installation of the driver found.

    文章目录: 1 错误原因 2 解决方法 1 错误原因 安装cuda的时候提示有多个显卡驱动:Existing package manager installation of the driver fo ...

  6. RPM是RedHat Package Manager(RedHat软件包管理工具)类似Windows里面的“添加/删除程序”...

    rpm 执行安装包 二进制包(Binary)以及源代码包(Source)两种.二进制包可以直接安装在计算机中,而源代码包将会由RPM自动编译.安装.源代码包经常以src.rpm作为后缀名. 常用命令组 ...

  7. 在Synaptic Package Manager 加载USB 接口的CD-ROM

    1因为Synaptic Package Manager 会去根目录下查找文件夹/cdrom, 但是新的Ubuntu 会把USB CDROM(/dev/sr0) mount 到 /media/Ubunt ...

  8. Package Manager Console 向VS2010安装 EntityFramework

    尝试用VS2010--工具--Library Package Manager--Add Library Package Reference的online搜索 EntityFramework, 再找到的 ...

  9. Unity Package Manager Error的解决方案

    问题来源 启动Unity时显示 fail to start Unity Package Manager,软件环境为 Unity 2017.3.0f3. 解决方案 根据网上所给的方案,我选择添加环境变量 ...

最新文章

  1. 分不清的InputStream和OutputStream
  2. 白炽灯可控硅调光程序
  3. mxnet基础到提高(38)-自动梯度计算
  4. 如何将SAP云平台Neo环境的Subaccount注册到IAS服务里
  5. linux c语 curl代码_偷懒必备工具——一键生成爬虫代码
  6. 云原生时代|分布式系统设计知识图谱(内含22个知识点)
  7. 2018前端学习总结
  8. Qt4_坐标系统变换
  9. 蓝桥杯官网题库【简单题解析】持续更新
  10. 中医针灸学综合练习题库【10】
  11. Completed 406 NOT_ACCEPTABLE
  12. 微信小程序 获取用户手机屏幕高度与宽度
  13. 【新知实验室】TRTC视频会议
  14. 如何将PPT进行压缩?简单的方法介绍
  15. Windows程序设计最新书籍教程
  16. cpu是几核的怎么查看
  17. Web前端--HTML+CSS+JS实现圣诞抓礼物小游戏
  18. 计算机图形学学习记录 系统及图形硬件
  19. 三十学艺与 Linux Networking Cookbook
  20. 基于Matlab生成并可视化多架飞机轨迹仿真(附源码)

热门文章

  1. 虚拟实验室中的事务管理系统(一、概述)
  2. C#为什么多线程控制winform需要用委托?
  3. PHP中session的工作原理
  4. MSTP和MPLS专线有什么区别?——Vecloud
  5. IT常说的协议指的是什么?—Vecloud微云
  6. Ajax的beforeSend 和 complete
  7. 禁用Browser Link
  8. ZOJ 3776 A - Pokemon Master 签到水题
  9. java selenium验证元素是否存在
  10. POJ 3034 Whac-a-Mole [DP]