【发布时间】:2012-10-12 18:38:57
【问题描述】:
我的行为很奇怪,我想我更多的是在寻找解释而不是解决方案(尽管也欢迎解决方案!)。
代码如下:
PackageManager pm = context.getPackageManager();
List<PackageInfo> pkgList = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
if (pkgList == null)
return null;
for (PackageInfo pkgInfo : pkgList) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
// do some stuff, doesn't modify pkgInfo or appInfo or pkgList
}
在某些情况下,我会收到以下错误日志:
java.lang.ClassCastException: 无法转换为 android.content.pm.PackageInfo
报告线路:
for (PackageInfo pkgInfo : pkgList)
奇怪的是,ClassCastException 通常看起来像 (AFAIK):
java.lang.ClassCastException: foo.bar.ClassA 无法转换为 foo.bar.ClassB
但是,我看到的错误在第一部分显示为空白。
我决定研究一下,如果返回列表的函数在内部强制转换错误的对象列表并返回它或其他东西,可能会发生这种情况。于是我看了看:
ApplicationPackageManager.getInstalledPackages()
@SuppressWarnings("unchecked")
@Override
public List<PackageInfo> getInstalledPackages(int flags) {
try {
final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
PackageInfo lastItem = null;
ParceledListSlice<PackageInfo> slice;
do {
final String lastKey = lastItem != null ? lastItem.packageName : null;
slice = mPM.getInstalledPackages(flags, lastKey);
lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
} while (!slice.isLastSlice());
return packageInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
好的,所以返回的列表是从ParceledListSlice.populateList()... 填充的
ParceledListSlice.populateList()
public T populateList(List<T> list, Creator<T> creator) {
mParcel.setDataPosition(0);
T item = null;
for (int i = 0; i < mNumItems; i++) {
item = creator.createFromParcel(mParcel);
list.add(item);
}
mParcel.recycle();
mParcel = null;
return item;
}
所以项目是从PackageInfo.CREATOR.createFromParcel()...创建的。
最后是PackageInfo 的creator.createFromParcel
public static final Parcelable.Creator<PackageInfo> CREATOR
= new Parcelable.Creator<PackageInfo>() {
public PackageInfo createFromParcel(Parcel source) {
return new PackageInfo(source);
}
public PackageInfo[] newArray(int size) {
return new PackageInfo[size];
}
};
所以一切似乎都很好。它正在创建一个PackageInfo 类型的ParceledListSlice,因此在populateList 中它正在创建一个PackageInfo 项目并将其放入List 的PackageInfo 中,这是返回的列表。所有类型/类对我来说都很好。
所以我的问题,
- 上面的ClassCastException是怎么发生的?
- 为什么会显示“空白”类型的错误消息?
- 什么是可能的解决方案?
我正在考虑将列表作为Object 的列表并检查“instanceof”,但我认为这也行不通,因为它可能最终会说
ClassCastException: cannot be cast into java.lang.Object" 什么的。
任何关于如何发生这种情况的见解和解释将不胜感激。
- Dalvik/JVM 只是搞砸了吗?
- 内存是否已损坏?
我只能胡乱猜测 =)
【问题讨论】:
-
如果您尝试手动遍历列表并打印出每个项目的类型怎么办?
-
@NathanVillaescusa 这是来自客户设备的日志,所以我不能这样做。它也不是 100% 可重现的。而且,我不认为我可以遍历每个项目并打印出类型,因为当我尝试获取该项目时,我认为它可能会抛出 ClassCastException。
-
我在想一个传统的
for loop,你循环到pkgList的长度。这将告诉您列表中的某些项目是否属于PackageInfo类。 -
我猜你的意思是做一个 for (int i = 0; i
-
无论如何,这不是我可以重现的问题,并且日志来自客户设备,所以我不能真正放置一些调试日志并将其推送并返回日志=(尽管感谢您的建议=) 我会很高兴从上面给定的代码中理解这样的日志是如何可能的。
标签: java android exception classcastexception android-package-managers