2016-12-07 121 views
0

這裏下面是例外日誌:爲什麼它拋出ClassCastException異常:的char []不能轉換爲android.app.SharedPreferencesImpl

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 : 

在這裏,下面有例外拋出在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; 
} 

讓我們假設日誌信息是正確的,它應該是幾乎正確的。

我的第一個問題是:在ContextImpl.java文件中引發358行異常拋出異常是什麼意思?那裏只有一個正確的支撐。

我猜低於線358的語句是例外

sp = packagePrefs.get(name); 

的根本情況,因爲SP被宣佈爲SharedPreferencesImpl,它應該有一個轉換操作時,get方法返回和分配,如果該值return是一個char [],那麼拋出的異常應該拋出,這個解釋是非常合理的。但在packagePrefs值已參數化爲SharedPreferencesImpl聲明一次在

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

因此,應該沒有機會把的char []的值類型爲packagePrefs。然後,我再次感到困惑,代碼出現在這個例外以及爲什麼。

還有一個類似的問題,日誌是:

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) 

以及相應的代碼是在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); 
     } 
    } 

它既似乎是通用的問題。希望這裏的專家提供幫助,並提前感謝。

+0

getSharedPreferences(String name,int mode)'方法是什麼包和類?堆棧跟蹤中的名稱有兩個方法,包含不同的包。你確定***你已經向我們展示了正確的方法嗎? –

+0

該方法是在android.app.ContextImpl類,我已經更新。你怎麼能知道堆棧跟蹤中有兩種方法,包含不同的包?你能爲我解釋清楚嗎?也許根情況是在其他軟件包中使用了錯誤的類。 – Saint

+0

您是否有理由相信其他代碼路徑可能會將'char []'對象插入這些數據結構中(例如,您在別處使用'char []'對象並將它們存儲在類似的地方)? – dimo414

回答

0

第一個問題(行號與錯誤不對應)我估計自上次編譯以來增加了三行(可能是name = "null"條件)。任何時候你都會看到堆棧跟蹤看起來不太對齊,這就暗示你的源代碼和你的二進制代碼不同步。

對於第二個問題,我們不應該看到ClassCastException因爲packagePrefsmLogRecVector是通用的,我會同意,這似乎是不可能的,如果你的代碼片段編譯(你可能會遇到的問題,如果sSharedPrefs是一個原始類型,但我假設情況並非如此)。我的第一個理論是你需要重新構建(脫離堆棧跟蹤與你的源代碼不一致的提示)。

如果完全重建不起作用,我不得不認爲這是一個Android特定的問題(也許您正在使用ProGuard?)。你能夠在OracleJDK或OpenJDK中複製這個嗎?如果您可以創建一個MCVE,我們可以通過它複製問題將有助於達到此目的。

+0

對於第一個問題,您是對的,我誤解了測試人員提供的版本代碼中日期信息的含義。 358行指向sp = packagePrefs.get(name);源代碼與二進制一致後。而且這個方法自創建以來從未改變過。 此問題發生在用戶的手機上,它隨便發生,我們無法複製它。 – Saint

+0

我不確定如果它不能被複制,我們可以得到多少幫助。他們的手機有什麼奇怪的,例如運行舊版Android? – dimo414

相關問題