Android ClassCastException with empty type

I get weird behavior, and I think I'm more looking for an explanation than a solution (although a solution is also welcome!).

Here is the code:

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 } 

And in some cases, I get error logs with:

java.lang.ClassCastException: cannot be added to android.content.pm.PackageInfo

for string:

 for (PackageInfo pkgInfo : pkgList) 

The odd part is that usually a ClassCastException usually looks like (AFAIK):

java.lang.ClassCastException: foo.bar.ClassA cannot be attributed to foo.bar.ClassB

However, the error that I see shows a blank for the first part.

I decided to investigate a bit, and something like that this could happen if the function returning the list internally discards the invalid list of objects and returns it or something like that. So I looked:

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

So, the list that is returned is populated from 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; } 

So, the item is created from PackageInfo.CREATOR.createFromParcel() ...

And finally creator.createFromParcel of PackageInfo

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

So everything looks fine. It creates a ParceledListSlice type PackageInfo , so in the populateList it creates a PackageInfo element and places it in the List of PackageInfo , which is the returned list. All types / classes seem fine to me.

So my questions are

  • How could the above ClassCastException occur?
  • Why should it show a "blank" type of error message?
  • And what would be a possible solution?

I was thinking of just getting the list as an Object list and checking " instanceof ", but I don't think this will work, because it will probably end up

ClassCastException: Cannot insert into java.lang.Object "or anything else.

It would be helpful to get any ideas and explanations as to how this could happen.

  • Is Dalvik / JVM just messy?
  • Is the memory corrupt?

I could only come up with wild assumptions =)

+8
java android exception android-package-managers classcastexception
source share
2 answers

If you are sure you are getting a ClassCastException exact string

 for (PackageInfo pkgInfo : pkgList) 

when the reason arises - somehow pkgList contains the value of the PackageInfo class. I assume this is NULL . Why don't you see it in the ClassCast error message, because the className for the NULL object is just an empty string.

Now, how to solve this - use the guide for the loop. The for aech uses an Iterator under the hood, so you have no control over casting a class at each iteration. But if you use this code:

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

You can control the class.

Alternatively, you can catch a ClassCastException and simply skip this step of the loop until the next.

0
source share

This seems to be a problem in Android. I found some error messages regarding Android that show similar behaviors:

Issue 26644: ClassCastException and IncompatibleClassChangeError

Issue 36560: Exception in (SensorManager.java∗21)

I also saw the IncompatibleClassChangeError mentioned in release 26644. I only assume that these seemingly impossible exceptions / errors are due to some strange memory corruption or dalvik / jvm problem. There seems to be nothing wrong with the code itself. If anyone has a better explanation, feel free to chip in =)

0
source share

All Articles