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了。
转载其他人的,谢谢 这位大神!