日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

RuntimeException: Package manager has died

發(fā)布時(shí)間:2025/4/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RuntimeException: Package manager has died 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文出處: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)

出現(xiàn)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); }

這是一個(gè)Binder調(diào)用,造成這個(gè)的原因是因?yàn)榘l(fā)生了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的使用超出了一個(gè)進(jìn)程的限制就會(huì)拋出TransactionTooLargeException這個(gè)異常。如果是其他原因造成Binder crash的話就會(huì)拋出RuntimeException。

那一個(gè)進(jìn)程的Binder內(nèi)存限制是多少?

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

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

這便是一個(gè)進(jìn)程中binder的大小,大約1M。

給Binder分配內(nèi)存的代碼:

#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; }

通過(guò)上面的清理,知道了如果一個(gè)進(jìn)程中使用的Binder內(nèi)容超過(guò)了1M,就會(huì)crash.

而如果這時(shí)候恰巧在用getPackageManager()做事情,就會(huì)提示Package manager has died

可以事實(shí)真的是這樣的嗎?

寫(xiě)了個(gè)demo來(lái)證明一下

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(); } } }

這個(gè)Demo就是同時(shí)創(chuàng)建兩個(gè)線程來(lái)進(jìn)行Binder調(diào)用

運(yùn)行打印的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

此時(shí)也如預(yù)期發(fā)生了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

解決方式

其實(shí)只要避免多個(gè)線程同時(shí)來(lái)調(diào)用Binder就可以了,畢竟一個(gè)線程用了會(huì)釋放,所以理論上是很難發(fā)生的。

修改后的Demo

synchronized(MainActivity.class){ PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName,PackageManager.GET_ACTIVITIES); }

再次運(yùn)行就不會(huì)Crash了

總結(jié)

以上是生活随笔為你收集整理的RuntimeException: Package manager has died的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。