8

私は奇妙な行動をとっています、そして私は解決策よりも説明を探していると思います(解決策も歓迎されますが!)。

コードは次のとおりです。

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

そして最後creator.createFromParcelPackageInfo

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

だから、すべてが大丈夫のようです。ParceledListSliceタイプのを作成しているPackageInfoのでpopulateList、アイテムを作成して、返されたリストであるのにPackageInfo入れます。すべてのタイプ/クラスは私には問題ないようです。ListPackageInfo

だから私の質問、

  1. 上記のClassCastExceptionはどのように発生しますか?
  2. エラーメッセージに「空白」タイプが表示されるのはなぜですか?
  3. そして、可能な解決策は何でしょうか?

リストをリストにObjectして「」をチェックするinstanceofことを考えていたのですが、おそらく「」と言ってしまうので、それもうまくいくとは思いません。

ClassCastException:java.lang.Object"などにキャストできません。

これがどのように発生するかについての洞察と説明をいただければ幸いです。

  1. Dalvik / JVMは単に混乱していますか?
  2. メモリが破損していますか?

私は野生の推測しか思いつかなかった=)

4

2 に答える 2

0

これは Android 自体の問題のようです。同様の動作を示す Android に対するバグ レポートをいくつか見つけました。

問題 26644: ClassCastException と IncompatibleClassChangeError

問題 36560: (SensorManager.java:521) での例外

問題 26644 にも記載されている IncompatibleClassChangeError も確認しました。私の唯一の推測では、これらの不可能に見える例外/エラーは、奇妙なメモリ破損またはdalvik/jvmの問題が原因であるということです。コード自体に問題があるようには見えません。他の誰かがより良い説明を持っている場合は、気軽に参加してください =)

于 2012-10-23T22:20:57.913 に答える
0

ClassCastException この行に正確に入ることが確実な場合

for (PackageInfo pkgInfo : pkgList)

理由が次の場合 - どういうわけかクラスpkgListではない値が含まれています。PackageInfoこれがNULL価値だと思います。classNameNULL オブジェクトは単なる空の文字列であるため、ClassCast エラー メッセージに表示されないのはなぜですか。

さて、これを解決する方法 - manual for loop を使用してください。for eachループは内部で使用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して、次のステップにスキップすることもできます。

于 2012-10-23T11:48:48.010 に答える