Android ClassCastException与空白types

我得到一个奇怪的行为,我想我更多地寻求解释,而不是一个解决scheme(尽pipe解决scheme也是受欢迎的!)。

代码如下:

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()...

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()创build的…

最后是PackageInfocreator.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]; } }; 

所以一切似乎都没问题 它创build一个ParceledListSlicetypes的ParceledListSlice ,所以在populateList创build一个PackageInfo项目,并把它放入一个PackageInfo List中,这是返回的列表。 所有的types/类对我来说都很好。

所以我的问题,

  1. 上面的ClassCastException如何发生?
  2. 为什么会显示错误信息的“空白”types?
  3. 什么是可能的解决scheme?

我正在考虑将列表作为Object的列表并检查“ instanceof ”,但是我不认为这样做可能会最终导致

ClassCastException:不能被转换成java.lang.Object“或其他东西。

任何有关如何发生的见解和解释将不胜感激。

  1. Dalvik / JVM只是搞乱了吗?
  2. 内存是否损坏?

我只能拿出狂野的猜测=)

Solutions Collecting From Web of "Android ClassCastException与空白types"

如果确定在这一行中确实得到了ClassCastException

 for (PackageInfo pkgInfo : pkgList) 

当一个原因如下 – 不知何故pkgList包含一个不是PackageInfo类的值。 我假设这是NULL值。 这就是为什么在ClassCast错误消息中看不到它,因为NULL对象的className只是空string。

现在,如何解决这个问题 – 使用循环手册。 for aech循环而言,在引擎盖下使用Iterator ,所以在每次迭代中你都不能控制类的强制转换。 但是,如果你会使用这样的代码:

 for (int i = 0; i < pkgList.length; i++) { Object pkgInfoObj = pkgList.get(i); if (pkgInfoObj instanceof PackageInfo) { PackageInfo pkgInfo = (PackageInfo) pkgInfoObj; ApplicationInfo appInfo = pkgInfo.applicationInfo; // do some stuff, doesn't modify pkgInfo or appInfo or pkgList } } 

你将能够控制类的铸造。

此外,你可以捕获 ClassCastException ,只是跳过这个循环步骤到下一个。

这似乎是Android本身的一个问题。 我发现了一些针对Android的错误报告,显示了类似的行为:

问题26644:ClassCastException和IncompatibleClassChangeError

问题36560:exception(SensorManager.java:521)

我也看到了问题26644中提到的IncompatibleClassChangeError。 我唯一的猜测是,这些看似不可能的exception/错误是由于一些奇怪的内存损坏或dalvik / jvm问题。 它似乎没有代码本身有什么问题。 如果其他人有更好的解释,请随时切入=)