java.lang.NoClassDefFoundError的原因及解決


[O]

 

安卓應用在低版本(V2.3.6)系統上運行時報錯: java.lang.NoClassDefFoundError

 

完整錯誤信息如下:

05-29 13:56:13.687: E/AndroidRuntime(3538): FATAL EXCEPTION: main
05-29 13:56:13.687: E/AndroidRuntime(3538): java.lang.NoClassDefFoundError: com.uustudio.unote.android.BaseApplication$1
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at com.uustudio.unote.android.BaseApplication.onCreate(BaseApplication.java:109)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3276)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.app.ActivityThread.access$2200(ActivityThread.java:117)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:973)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.os.Handler.dispatchMessage(Handler.java:99)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.os.Looper.loop(Looper.java:130)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at android.app.ActivityThread.main(ActivityThread.java:3687)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at java.lang.reflect.Method.invokeNative(Native Method)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at java.lang.reflect.Method.invoke(Method.java:507)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
05-29 13:56:13.687: E/AndroidRuntime(3538): 	at dalvik.system.NativeStart.main(Native Method)

 

簡化后:

E/AndroidRuntime(3538): FATAL EXCEPTION: main
E/AndroidRuntime(3538): java.lang.NoClassDefFoundError: com.uustudio.unote.android.BaseApplication$1
at com.uustudio.unote.android.BaseApplication.onCreate(BaseApplication.java:109)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:969)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3276)
at android.app.ActivityThread.access$2200(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:973)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)

 

 

1. 一種解決方案如鏈接:http://blog.csdn.net/leehong2005/article/details/9407111

未生效

 

2. 一種解決方案:Properties->Java Build Path 選擇Source分頁添加Libs路徑,從而將第三方jar包打包進apk

未生效

 

3. 過程中出現新問題:Unable to execute dex: Multiple dex files define Lcom/myapp/R$array;

解決方案:http://stackoverflow.com/questions/7870265/unable-to-execute-dex-multiple-dex-files-define-lcom-myapp-rarray

 

4. 一種解決方案,此種應該是離問題原因很近的:http://blog.csdn.net/tianjian4592/article/details/43467283

依然未生效,但可基本判斷是配置沖突或配置未生效造成的,需要clean之后重新配置。

(然而測試之后發現並非如此...)

 

以上解決辦法均針對安卓工程引用第三方jar包這一原因,我的情況是在部分機型(高版本安卓系統)及模擬器運行正常,在部分機型(安卓系統2.3.6)測試時出現問題,若是上述原因,則所有機型均無法正常運行才對,故排除。

 

5. 一種原因分析:AsyncTask陷阱之:Handler,Looper與MessageQueue的詳解

在該問題案例中,程序在安卓2.3版本的機器上無法運行,在4.0及以上版本運行OK,其原因是程序中的Handler對象未進行BindApplication,而4.0及以上版本系統會自動進行該操作,該文章相關內容如下:

從2.3運行時的Stacktrace來看原因是在非UI線程中操作了UI組件。不對呀,神奇 啊,AsyncTask#onProgressUpdate()和AsyncTask#onPostExecute()的文檔明明寫着這二個回調是在UI 線程里面的嘛,怎么還會報出這樣的異常呢!


AsyncTask設計出來執行異步任務卻又能與主線程通訊,它的內部有一個 InternalHandler是繼承自Handler的靜態成員sHandler,這個sHandler就是用來與主線程通訊的。看下這個對象的聲 明:private static final InternalHandler sHandler = new InternalHandler();而InternalHandler又是繼承自Handler的。所以本質上講sHandler就是一個 Handler對象。Handler是用來與線程通訊用的,它必須與Looper和線程綁定一起使用,創建Handler時必須指定Looper,如果不 指定Looper對象則使用調用棧所在的線程,如果調用棧線程沒有Looper會報出異常。看來這個sHandler是與調用new InternalHandler()的線程所綁定,它又是靜態私有的,也就是與第一次創建AsyncTask對象的線程綁定。所以,如果是在主線程中創建 的AsyncTask對象,那么其sHandler就與主線程綁定,這是正常的情況。在此例子中AsyncTask是在衍生線程里創建的,所以其 sHandler就與衍生線程綁定,因此,它自然不能操作UI元素,會在onProgressUpdate()和onPostExecute()中拋出異常。

 

以上例子有異常的原因就是在衍生線程中創建了SimpleAsyncTask對象。至於為什么在4.0版本上沒有問題,是因為4.0 中在ActivityThread.main()方法中,會進行BindApplication的動作,這時會用AsyncTask對象,也會創建 sHandler對象,這是主線程所以sHandler是與主線程綁定的。后面再創建AsyncTask對象時,因為sHandler已經初始化完了,不 會再次初始化。至於什么是BindApplication,為什么會進行BindApplication的動作不影響這個問題的討論。AsyncTask的缺陷及修改方法。

 

這其實是AsyncTask的隱藏的Bug,它不應該這么依賴開發者,應該強加條件限制,以保證第一次AsyncTask對象是在主線程中創建。

 

該問題及原因描述與我遇到的情況及錯誤日志信息極為相近,為驗證之,新建安卓2.2和2.3版本的模擬器並運行代碼。

 - 在安卓2.2版本系統的模擬器下運行,報出同樣錯誤及Log信息。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM