本人最近研究Android内存动态加载dex文件,做了个小实验。实现了两个APK程序A和B,程序A运行的时候会把程序B的dex文件读到内存中,然后加载B中的类,并调用其方法。
程序A实现的大概步骤是:
1. 在java层将B中的dex文件读到内存中;
2. 然后参照系统解析dex文件的函数Dalvik_dalvik_system_DexFile_openDexFile_bytearray,我自己实现了解析dex文件的函数,将其解析成DexOrJar类型的对象;
3. 然后调用dvmHashTableLookup把这个对象添加到gDvm.userDexFiles这个hashtable中;
4. 然后把DexOrJar对象的指针返回到java层,利用Java的反射机制,新建一个Element对象,并将其添加到程序ClassLoader中的DexPathList中的dexElements数组中去。
上面是大概的步骤和逻辑,参照的是http://bbs.pediy.com/showthread.php?t=205577这个帖子,实验手机的系统是4.3。
在运行A程序的时候程序B中的类可以找到,但是在调用类中方法的时候会偶现崩溃,崩溃栈如下:
02-18 05:08:26.037: I/DEBUG(169): backtrace:
02-18 05:08:26.037: I/DEBUG(169): #00 pc 000699f6 /system/lib/libdvm.so (dvmLinkClass(ClassObject*)+477)
02-18 05:08:26.037: I/DEBUG(169): #01 pc 0006aa89 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #02 pc 00064c69 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #03 pc 00027060 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #04 pc 0002b5ec /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
02-18 05:08:26.037: I/DEBUG(169): #05 pc 0005ff21 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+292)
02-18 05:08:26.037: I/DEBUG(169): #06 pc 0005ff4b /system/lib/libdvm.so (dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...)+20)
02-18 05:08:26.037: I/DEBUG(169): #07 pc 0006ac8d /system/lib/libdvm.so (dvmFindClassNoInit(char const*, Object*)+112)
02-18 05:08:26.037: I/DEBUG(169): #08 pc 0006bb5d /system/lib/libdvm.so (dvmResolveClass+48)
02-18 05:08:26.037: I/DEBUG(169): #09 pc 0006993d /system/lib/libdvm.so (dvmLinkClass(ClassObject*)+292)
02-18 05:08:26.037: I/DEBUG(169): #10 pc 0006aa89 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #11 pc 00064c69 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #12 pc 00027060 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #13 pc 0002b5ec /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
02-18 05:08:26.037: I/DEBUG(169): #14 pc 000601df /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+350)
02-18 05:08:26.037: I/DEBUG(169): #15 pc 00067ddf /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #16 pc 00027060 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #17 pc 0002b5ec /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
02-18 05:08:26.037: I/DEBUG(169): #18 pc 0005ff21 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+292)
02-18 05:08:26.037: I/DEBUG(169): #19 pc 00049b67 /system/lib/libdvm.so
02-18 05:08:26.037: I/DEBUG(169): #20 pc 0004b697 /system/lib/libandroid_runtime.so
02-18 05:08:26.037: I/DEBUG(169): #21 pc 0004c327 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+378)
02-18 05:08:26.037: I/DEBUG(169): #22 pc 0000105b /system/bin/app_process
02-18 05:08:26.037: I/DEBUG(169): #23 pc 0000db4f /system/lib/libc.so (__libc_init+50)
02-18 05:08:26.037: I/DEBUG(169): #24 pc 00000d7c /system/bin/app_process
很奇怪的是崩溃是偶现的,有的时候会执行没问题,我用IDA跟踪了好长时间也没发现问题。在这里请教一下万能的看雪论坛,上面我的实现逻辑里面是不是有什么问题?
另外,我做这个实验主要是因为程序加壳以后,在程序启动时解壳并加载原始dex的时候耗时非常严重,想找到一个快速加载dex的方法,上面的这个方法应该会有很大的适配问题,如果大家有其他可以快速加载dex的方法希望不吝赐教啊,谢谢!!