0x00
在上一篇文章apk安装和优化原理,在最后我们分析了DexClassLoader和PathClassLoader的构造函数的不同。
PathClassLoader最后调用的是new DexFile(pathFile),而DexClassLoader调用的是DexFile.loadDex(dexPathList[i], outputName, 0)。
0x01
new DexFile(pathFile)对应的代码位于libcore\dalvik\src\main\java\dalvik\system\DexFile.java。
public DexFile(String fileName) throws IOException {
String wantDex = System.getProperty("android.vm.dexfile", "false");
if (!wantDex.equals("true"))
throw new UnsupportedOperationException("No dex in this VM");
mCookie = openDexFile(fileName, null, 0);
mFileName = fileName;
//System.out.println("DEX FILE cookie is " + mCookie);
}
DexFile.loadDex(dexPathList[i], outputName, 0)对应的代码也位于libcore\dalvik\src\main\java\dalvik\system\DexFile.java。
static public DexFile loadDex(String sourcePathName, String outputPathName,
int flags) throws IOException {
/*
* TODO: we may want to cache previously-opened DexFile objects.
* The cache would be synchronized with close(). This would help
* us avoid mapping the same DEX more than once when an app
* decided to open it multiple times. In practice this may not
* be a real issue.
*/
return new DexFile(sourcePathName, outputPathName, flags);
}
private DexFile(String sourceName, String outputName, int flags)
throws IOException {
String wantDex = System.getProperty("android.vm.dexfile", "false");
if (!wantDex.equals("true"))
throw new UnsupportedOperationException("No dex in this VM");
mCookie = openDexFile(sourceName, outputName, flags);
mFileName = sourceName;
//System.out.println("DEX FILE cookie is " + mCookie);
}
我们可以看到其实两者最终调用的都是openDexFile,只不过
DexClass
Loader指定了生成优化后的apk路
径,而PathClassLoader则不需要,因为在安装阶段已经生成了/data/dalvik-cache/xxx@classes.dex。
0x02
我们继续分析openDexFile,这个方法一个JNI方法。
native private static int openDexFile(String sourceName, String outputName,
int flags) throws IOException;
代码位于
libcore\dalvik\src\main\java\dalvik\system\
DexFile.java。
对应的native方法位于dalvik\vm\native\dalvik_system_DexFile.c。
const DalvikNativeMethod dvm_dalvik_system_DexFile[] = {
{ "openDexFile", "(Ljava/lang/String;Ljava/lang/String;I)I",
Dalvik_dalvik_system_DexFile_openDexFile },
{ "closeDexFile", "(I)V",
Dalvik_dalvik_system_DexFile_closeDexFile },
{ "defineClass", "(Ljava/lang/String;Ljava/lang/ClassLoader;ILjava/security/ProtectionDomain;)Ljava/lang/Class;",
Dalvik_dalvik_system_DexFile_defineClass },
{ "getClassNameList", "(I)[Ljava/lang/String;",
Dalvik_dalvik_system_DexFile_getClassNameList },
{ "isDexOptNeeded", "(Ljava/lang/String;)Z",
Dalvik_dalvik_system_DexFile_isDexOptNeeded },
{ NULL, NULL, NULL },
};
我们看到openDexFile对应的是Dalvik_dalvik_system_DexFile_openDexFile方法。