Invalid indirect reference 0x41e0cba8 in decodeIndirectRef

10-08 11:20:13.636: W/dalvikvm(9450): Invalid indirect reference 0x41e0cba8 in decodeIndirectRef
10-08 11:20:13.636: I/dalvikvm(9450): "main" prio=5 tid=1 RUNNABLE
10-08 11:20:13.636: I/dalvikvm(9450):   | group="main" sCount=0 dsCount=0 obj=0x4161af18 self=0x415367a0
10-08 11:20:13.636: I/dalvikvm(9450):   | sysTid=9450 nice=0 sched=0/0 cgrp=apps handle=1074135380
10-08 11:20:13.636: I/dalvikvm(9450):   | state=R schedstat=( 1404771012 144058057 708 ) utm=134 stm=6 core=0
10-08 11:20:13.636: I/dalvikvm(9450):   at java.lang.Class.getDex(Native Method)
10-08 11:20:13.636: I/dalvikvm(9450):   at libcore.reflect.AnnotationAccess.getSignature(AnnotationAccess.java:447)
10-08 11:20:13.636: I/dalvikvm(9450):   at java.lang.Class.getGenericSuperclass(Class.java:824)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.com.google.gson.reflect.TypeToken.a(SourceFile:83)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.com.google.gson.reflect.TypeToken.<init>(SourceFile:63)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.harvest.type.BaseHarvestable$1.<init>(SourceFile:17)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.harvest.type.BaseHarvestable.<init>(SourceFile:16)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.harvest.type.HarvestableArray.<init>(SourceFile:7)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.harvest.ApplicationInformation.<init>(SourceFile:29)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.j.n.e(SourceFile:294)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.j.n.w(SourceFile:825)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.j.n.<init>(SourceFile:144)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.j.n.d(SourceFile:631)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.networkbench.agent.impl.NBSAppAgent.start(SourceFile:205)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.ppdai.loan.PPDaiApplication.onCreate(PPDaiApplication.java:69)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.payegis.ProxyApplication.oncreate(Native Method)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.payegis.ProxyApplication.onCreate(ProxyApplication.java:13)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1009)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4632)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.app.ActivityThread.access$1800(ActivityThread.java:141)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.os.Handler.dispatchMessage(Handler.java:102)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.os.Looper.loop(Looper.java:136)
10-08 11:20:13.636: I/dalvikvm(9450):   at android.app.ActivityThread.main(ActivityThread.java:5336)
10-08 11:20:13.636: I/dalvikvm(9450):   at java.lang.reflect.Method.invokeNative(Native Method)
10-08 11:20:13.636: I/dalvikvm(9450):   at java.lang.reflect.Method.invoke(Method.java:515)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
10-08 11:20:13.636: I/dalvikvm(9450):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:687)
10-08 11:20:13.636: I/dalvikvm(9450):   at dalvik.system.NativeStart.main(Native Method)
10-08 11:20:13.636: E/dalvikvm(9450): VM aborting

很明顯,是因爲應用調用了 java.lang.Class.getTypeParameters()方法導致的問題,這個方法是用來獲取泛型數量,在GSON或fastjson這樣的第三方JSON反射框架中會出現這樣的調用,出現這樣的問題也正是使用這樣的類庫出現的。爲什麼只會在android4.4系統中出現這樣的兼容性問題,而其他版本沒有?從堆棧錯誤信息中可以看出來,在Java層最後調用的一個方法是Class.getDex(),這個是個native方法,只在C++代碼中實現,而android其他版本卻沒有這個方法。查看dalvik/vm/native/java_lang_Class.cpp中的JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass)函數發現,在NDK中new一個Dex對象,而在這個對象時傳的參數爲空,導致在java層通過下標訪問時出現了java.lang.IndexOutOfBoundsException異常,這也解釋了爲什麼會出現NewGlobalRef pending exception。最後在源碼中插入LOG,編譯驗證了一下,證明確實是這樣。

OK,問題產生的原因找到了,怎麼解決呢?

應用加載DEX文件時,調用了4.4新增了static void Dalvik_dalvik_system_DexFile_openDexFile_bytearray(const u4 args, JValue pResult)函數,直接將一個DEX文件的字節流傳入,虛擬機自動解析並加載類相關信息。雖然這個函數是static,但因爲使用到了NDK註冊的方式,將Java層的方法與C++層對應的函數綁定到了一起,這樣就可以使用指針遍歷dvm_dalvik_system_DexFile數組找到對應的函數指針,從而可以調用。而在Java層的DexFile類中沒有找到與之對應的int openDexFile(byte)方法,估計是被刪了,而這個函數又沒有被google官方驗證,所以種種巧合,掉進了這個坑。唉,不說了,都是淚啊。

最後問題還是解決了,根本原因是RawDexFile->pDvmDex->memMap指針爲空,分配內存賦值就O了。

轉載其他人的,謝謝 這位大神!

http://www.jacpy.com/2015/05/10/android-4-4-call-class-gettypeparameters-occur-jni-function-newglobalref-called-with-exception-pending.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章