您的位置:首页 > 移动开发 > Android开发

Android培训班(68)dex文件打开流程

2011-09-04 14:21 441 查看
在上面的函数里,提到使用dvmJarFileOpen函数找到classes.dex文件,并加载到内存里,然后提供后面的函数使用。现在就来分析这个函数的代码,如下:intdvmJarFileOpen(const char* fileName, const char* odexOutputName, JarFile** ppJarFile, bool isBootstrap){在这里提供四个参数,第一个参数fileName是输入的Jar的文件名称;第二个参数odexOutputName是进行优化后的Dex输出文件;第三个参数ppJarFile是已经打开并缓存到内存里的文件对象;第四个参数isBootstrap是指示是否系统里Dex文件。
ZipArchive archive; DvmDex* pDvmDex = NULL; char* cachedName = NULL; bool archiveOpen = false; bool locked = false; int fd = -1; int result = -1;
/* Even if we're not going to look at thearchive, we need to * open it so we can stuff it intoppJarFile. */ if (dexZipOpenArchive(fileName, &archive)!= 0) goto bail; archiveOpen = true;这段代码是调用前面介绍的函数dexZipOpenArchive来打开Zip文件,并缓存到系统内存里。

/* If we fork/exec into dexopt, don't letit inherit the archive's fd. */ dvmSetCloseOnExec(dexZipGetArchiveFd(&archive));这行代码设置当执行完成后,关闭这个文件句柄。
/* First, look for a ".odex"alongside the jar file. It will * have the same name/path except for theextension. */ fd = openAlternateSuffix(fileName, "odex",O_RDONLY, &cachedName); if (fd >= 0) {这里优先处理优化的Dex文件。
LOGV("Using alternate file (odex)for %s ...\n", fileName); if (!dvmCheckOptHeaderAndDependencies(fd,false, 0, 0, true, true)) { LOGE("%s odex has staledependencies\n", fileName); free(cachedName); close(fd); fd = -1; goto tryArchive; } else { LOGV("%s odex has gooddependencies\n", fileName); //TODO: make sure that the .odexactually corresponds // to the classes.dex inside thearchive (if present). // For typical use there will beno classes.dex. } }else { ZipEntry entry;
tryArchive: /* * Pre-created .odex absent or stale. Look inside the jar for a * "classes.dex". */ entry = dexZipFindEntry(&archive,kDexInJarName);这行代码是从压缩包里找到Dex文件,然后打开这个文件。
if (entry != NULL) { bool newFile = false;
/* * We've found the one we want. Seeif there's an up-to-date copy * in the cache. * * On return, "fd" will beseeked just past the "opt" header. * * If a stale .odex file is presentand classes.dex exists in * the archive, this will *not*return an fd pointing to the * .odex file; the fd will point intodalvik-cache like any * other jar. */ if (odexOutputName == NULL) { cachedName =dexOptGenerateCacheFileName(fileName, kDexInJarName); if (cachedName == NULL) goto bail;这段代码是把Dex文件进行优化处理,并输出到指定的文件。
} else { cachedName =strdup(odexOutputName); } LOGV("dvmDexCacheStatus:Checking cache for %s (%s)\n", fileName, cachedName); fd = dvmOpenCachedDexFile(fileName,cachedName, dexGetZipEntryModTime(&archive,entry), dexGetZipEntryCrc32(&archive,entry), isBootstrap, &newFile,/*createIfMissing=*/true);这段代码创建缓存的优化文件。
if (fd < 0) { LOGI("Unable to open orcreate cache for %s (%s)\n", fileName, cachedName); goto bail; } locked = true;
/* * If fd points to a new file(because there was no cached version, * or the cached version was stale),generate the optimized DEX. * The file descriptor returned isstill locked, and is positioned * just past the optimization header. */ if (newFile) { u8 startWhen, extractWhen,endWhen; bool result; off_t dexOffset, fileLen;
dexOffset = lseek(fd, 0,SEEK_CUR); result = (dexOffset > 0);
if (result) { startWhen =dvmGetRelativeTimeUsec(); result =dexZipExtractEntryToFile(&archive, entry, fd); extractWhen =dvmGetRelativeTimeUsec();这段代码调用函数dexZipExtractEntryToFile从压缩包里解压文件出来。
} if (result) { result =dvmOptimizeDexFile(fd, dexOffset, dexGetZipEntryUncompLen(&archive,entry), fileName, dexGetZipEntryModTime(&archive,entry), dexGetZipEntryCrc32(&archive,entry), isBootstrap);这段代码调用函数dvmOptimizeDexFile对Dex文件进行优化处理。
}
if (!result) { LOGE("Unable toextract+optimize DEX from '%s'\n", fileName); goto bail; }
endWhen =dvmGetRelativeTimeUsec(); LOGD("DEX prep '%s': unzipin %dms, rewrite %dms\n", fileName, (int) (extractWhen -startWhen) / 1000, (int) (endWhen - extractWhen)/ 1000); } } else { LOGI("Zip is good, but no %sinside, and no valid .odex " "file in the samedirectory\n", kDexInJarName); goto bail; } }
/* * Map the cached version. This immediatelyrewinds the fd, so it * doesn't have to be seeked anywhere inparticular. */ if (dvmDexFileOpenFromFd(fd, &pDvmDex)!= 0) { LOGI("Unable to map %s in %s\n",kDexInJarName, fileName); goto bail; }这段代码是调用函数dvmDexFileOpenFromFd来缓存Dex文件,并分析文件的内容。比如标记是否优化的文件,通过签名检查Dex文件是否合法。

if (locked) { /* unlock the fd */ if (!dvmUnlockCachedDexFile(fd)) { /* uh oh -- this process needs toexit or we'll wedge the system */ LOGE("Unable to unlock DEXfile\n"); goto bail; } locked = false; }这段代码是保存文件到缓存里,标记这个文件句柄已经保存到缓存。

LOGV("Successfully opened '%s' in'%s'\n", kDexInJarName, fileName);
*ppJarFile = (JarFile*) calloc(1,sizeof(JarFile)); (*ppJarFile)->archive = archive; (*ppJarFile)->cacheFileName =cachedName; (*ppJarFile)->pDvmDex = pDvmDex; cachedName = NULL; // don't free itbelow result = 0;这段代码已经成功打开压缩包,并读取Dex文件到内存缓存,这里只是设置一些相关信息返回前面的函数处理。
bail: /* clean up, closing the open file */ if (archiveOpen && result != 0) dexZipCloseArchive(&archive); free(cachedName); if (fd >= 0) { if (locked) (void) dvmUnlockCachedDexFile(fd); close(fd); } return result;}
本函数主要流程是打开压缩文件,然后找到Dex文件,读取出来,并进行分析,然后拷贝到缓存里,再返回给调用函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: