下面来分析这个函数代码,如下:
intdexZipPrepArchive(int fd, const char* debugFileName, ZipArchive*pArchive)
{
这个函数输入文件句柄、文件名称、压缩文件对象。
MemMapping map;
int err;
map.addr = NULL;
memset(pArchive, 0, sizeof(*pArchive));
pArchive->mFd = fd;
这行代码是保存文件句柄。
if (sysMapFileInShmem(pArchive->mFd,&map) != 0) {
err = -1;
LOGW("Map of '%s' failed\n",debugFileName);
goto bail;
}
if (map.length < kEOCDLen) {
err = -1;
LOGV("File '%s' too small to be zip(%zd)\n", debugFileName,map.length);
goto bail;
}
这段代码映射文件数据到内存。
if (!parseZipArchive(pArchive, &map)) {
err = -1;
LOGV("Parsing '%s' failed\n",debugFileName);
goto bail;
}
这段代码是分析zip文件。
/* success */
err = 0;
sysCopyMap(&pArchive->mMap, &map);
map.addr = NULL;
这段代码拷贝到映射位置。
bail:
if (err != 0)
dexZipCloseArchive(pArchive);
if (map.addr != NULL)
sysReleaseShmem(&map);
return err;
}
函数dexZipPrepArchive的处理,主要就是先保存文件句柄,然后创建文件内存映射,调用parseZipArchive函数来分析zip的所有入口点,并记录到相应的hash表里,最后调用sysCopyMap函数来保存到zip文件对象结构里。
由上面分析可知,dex文件是压缩成zip文件,这样可以减少占用空间。dex文件在系统里是怎么样打开的过程呢?其它经过下面的过程:
1)系统初始化虚拟机时,会初始化原始方法gDvmNativeMethodSet集合。
2)在原始方法集合里有一个函数集合dvm_dalvik_system_DexFile,注册它为Ldalvik/system/DexFile串,当虚拟机调用DexFile相关函数时,就会调用这些函数来处理Dex文件。
3)在处理Dex文件时,会调用函数集合:dvm_dalvik_system_DexFile,这个函数集合里,主要有如下函数:
constDalvikNativeMethod 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,它是打开Dex文件函数。
closeDexFile方法对应的原始函数是Dalvik_dalvik_system_DexFile_closeDexFile,它是关闭已经打开的Dex文件函数。
4)在Dalvik_dalvik_system_DexFile_openDexFile函数里,调用函数dvmJarFileOpen打开JAR或者ZIP压缩的文件。
5)在dvmJarFileOpen函数里,调用dexZipOpenArchive来处理ZIP文件,调用dexZipFindEntry函数读取ZIP解压的文件,调用dvmDexFileOpenFromFd函数读取相应的类数据到内存,并返回给虚拟机。