简体   繁体   中英

Why it throws ClassCastException: char[] cannot be cast to android.app.SharedPreferencesImpl

Here below are the exception logs:

java.lang.ClassCastException: char[] cannot be cast to android.app.SharedPreferencesImpl
at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:358)
at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:171)
at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:171)
at com.android.internal.telephony.cat.CatService.saveCmdToPreference(CatService.java:2632)
at com.android.internal.telephony.cat.CatService.handleDBHandler(CatService.java:2079)
at com.android.internal.telephony.cat.CatService.handleMessage(CatService.java:1841)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Loo|debug info:dalvik.system.VMStack.getThreadStackTrace(Native Method)|java.lang.Thread.getStackTrace(Thread.java:580)|java.lang.Thread.getAllStackTraces(Thread.java:522)|com.letv.bsp.crashhandler.utils.LogUtils.trace(LogUtils.java:86)|com.letv.bsp.crashhandler.CrashHandleService.reportException(CrashHandleService.java:915)|com.letv.bsp.crashhandler.CrashHandleService.onStartCommand(CrashHandleService.java:663)|android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3291)|android.app.ActivityThread.-wrap18(ActivityThread.java)|android.app.ActivityThread$H.handleMessage(ActivityThread.java:1674)|android.os.Handler.dispatchMessage(Handler.java:111)|android.os.Looper.loop(Looper.java:207)|android.app.ActivityThread.main(ActivityThread.java:5905)|java.lang.reflect.Method.invoke(Native Method)|com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)|com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)|, blk: false printBlacklist the current black list : 

And here below are the codes exception throws at android.app.ContextImpl.getSharedPreferences

    @Override
public SharedPreferences getSharedPreferences(String name, int mode) {
    SharedPreferencesImpl sp;
    synchronized (ContextImpl.class) {
        if (sSharedPrefs == null) {
            sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>();
        }

        final String packageName = getPackageName();
        ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
        if (packagePrefs == null) {
            packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
            sSharedPrefs.put(packageName, packagePrefs);
        }

        // At least one application in the world actually passes in a null
        // name.  This happened to work because when we generated the file name
        // we would stringify it to "null.xml".  Nice.
        if (mPackageInfo.getApplicationInfo().targetSdkVersion <
                Build.VERSION_CODES.KITKAT) {
            if (name == null) {
                name = "null";
            } // here is the line 358
        }

        sp = packagePrefs.get(name);
        if (sp == null) {
            File prefsFile = getSharedPrefsFile(name);
            sp = new SharedPreferencesImpl(prefsFile, mode);
            packagePrefs.put(name, sp);
            return sp;
        }
    }
    if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
        getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
        // If somebody else (some other process) changed the prefs
        // file behind our back, we reload it.  This has been the
        // historical (if undocumented) behavior.
        sp.startReloadIfChangedUnexpectedly();
    }
    return sp;
}

Let's suppose the log information is correct, and it should be correct almost.

My first question is: what does it mean by saying that throws cast exception at line 358 at ContextImpl.java file? There is only a right brace there.

I guess the statement below line 358 is the root case of the exception

sp = packagePrefs.get(name);

because sp is declare as SharedPreferencesImpl, and it should have a cast operation when the get method return and assignment, if the value return is a char[], then the cast exception should throw, this explanation is very reasonable. But the value in packagePrefs has parameterized as SharedPreferencesImpl once declare at

packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();

Therefore, it should have no chance to put a value type of char[] into packagePrefs. Then, I am confused again, where is the code occur this exception and why.

There is another similar problem, the log is:

    java.lang.ClassCastException: char[] cannot be cast to              com.android.internal.util.StateMachine$LogRec
at com.android.internal.util.StateMachine$LogRecords.add(StateMachine.java:665)
at com.android.internal.util.StateMachine$SmHandler.performTransitions(StateMachine.java:830)
at com.android.internal.util.StateMachine$SmHandler.handleMessage(StateMachine.java:801)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.os.HandlerThread.run(HandlerThread.java:61)

And the corresponding codes is at com.android.internal.util.StateMachine.LogRecords:

        private Vector<LogRec> mLogRecVector = new Vector<LogRec>();
        synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
            IState orgState, IState transToState) {
        mCount += 1;
        if (mLogRecVector.size() < mMaxSize) {
            mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
        } else {
            LogRec pmi = mLogRecVector.get(mOldestIndex);
            mOldestIndex += 1;
            if (mOldestIndex >= mMaxSize) {
                mOldestIndex = 0;
            }
            pmi.update(sm, msg, messageInfo, state, orgState, transToState);
        }
    }

It both seems to be a problem about generic. Hope help from experts here and thanks so much in advance.

To the first issue (that the line number doesn't correspond to the error) my guess is you added three lines (perhaps the name = "null" conditional) since last compiling. Any time you see stack traces that don't seem to line-up that's a strong hint that your source and your binary are out of sync.

For the second issue that we shouldn't see a ClassCastException because packagePrefs and mLogRecVector are generic, I'd agree this seems impossible if your code snippets compile (you might run into issues if sSharedPrefs were a raw type, but I'm assuming that's not the case). My first theory would be that you need to re-build (going off of the hint that the stack trace doesn't line up with your source code).

If a full rebuild doesn't work I'd have to assume this is an Android-specific issue (perhaps you're using ProGuard?). Are you able to replicate this in OracleJDK or OpenJDK? If you can create an MCVE that we can replicate the issue with it would help get to the bottom of this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM