Reference to:http://blog.csdn.net/xxooyc/article/details/50162523
This is one of the issue that was encountered today due to binder. Although it is relatively simple, keep a record of it.
Let's start by looking at crash log:
E/hpnsservice (24810): HPNS Version is 5.0java.lang.runtimeexception:package manager have 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 Co M.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 Meth OD) e/hpnsservice (24810): at Android.os.BinderProxy.transact (binder.java:496) E/hpnsservice (24810): at Andro Id.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
Why does package manager have died occur?
Frameworks/base/core/java/android/app/applicationpackagemanager.java:
102 @Override103 Public packageinfo getpackageinfo (String packagename, int flags) 104 throws namenotfoundexception { 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); 113114 throw new Namenotfoundexception (PackageName);
This is a binder call, and the reason for this is because RemoteException has occurred.
Then why do friends happen to RemoteException?
In fact, the following sentence caused By:android.os.TransactionTooLargeException caused.
Why does it cause transactiontoolargeexception?
Frameworks/base/core/jni/android_util_binder.cpp:
682 case failed_transaction:683 Aloge ("!!! FAILED BINDER TRANSACTION!!! "); 684//Transactiontoolargeexception is a checked exception and only throw from certain methods. 685//Fixme:transaction too large is the most common reason for failed_transaction 686// But it isn't the only one. The Binder driver can return br_failed_reply 687//For other reasons also, such as if the Transact Ion is malformed or 688//refers to a FD that have been closed. We should change the driver 689//To enable us to distinguish these cases on the future. 690 jnithrowexception (env, canthrowremoteexception 691?) "Android/os/transactiontoolargeexception" 692: "Java/lang/runtimeexception", NULL); 693 break;
It can be seen that if the use of binder exceeds the limit of a process, the transactiontoolargeexception exception is thrown.
If other reasons cause binder crash, it will throw runtimeexception.
What is the binder memory limit for that process?
Frameworks/native/libs/binder/processstate.cpp:
#define BINDER_VM_SIZE ((1*1024*1024)-(4096))
This is the size of the binder in a process, about 1M.
Code to allocate memory for binder:
349#if!defined (HAVE_WIN32_IPC) //Mmap The binder, providing a chunk of virtual address space to receive Tran Sactions. 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 }
Through the above cleanup, know that if the binder used in a process more than 1M, it will be crash.
And if this happens to be doing things with Getpackagemanager (), it will prompt package manager have died.
Can it be true that this is the case?
Wrote a demo to prove it:
public class Mainactivity extends Activity {@Override protected void onCreate (Bundle savedins Tancestate) {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:" + Co unt++); } catch (Namenotfoundexception e) {}}} }.start (); } } }
This demo is to create two threads at a time to make binder calls.
Run the printed 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
The crash also occurs as expected at this time:
E/javabinder (31244):!!! FAILED BINDER TRANSACTION!!! E/androidruntime (31244): FATAL exception:thread-4798 e/androidruntime (31244): Process:com.example.testdl, pid:3124 4 E/androidruntime (31244): Java.lang.RuntimeException:Package manager have died e/androidruntime (31244): at a Ndroid.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.Tr Ansactiontoolargeexception 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 Oid.app.ApplicationPackageManager.getPackageInfo (applicationpackagemanager.java:150) E/androidruntime (31244): ... 1 more D/enterprisedevicemanagerservice (3021): Ismana
How to resolve:
In fact, just avoid multiple threads at the same time to invoke the binder can be, after all, a thread will be released, so theoretically it is difficult to happen.
Modified Demo:
Synchronized (mainactivity.class) { packageinfo pi = Getpackagemanager () . Getpackageinfo (Info.packagename, packagemanager.get_activities); }
Running again will not crash.
[Android Pro] Analysis Package Manager have died