1. 程式人生 > >Android培訓班 68 dex文件打開流程

Android培訓班 68 dex文件打開流程

RoCE for -- 信息 返回 培訓班 des exec 代碼

在上面的函數裏,提到使用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文件,讀取出來,並進行分析,然後拷貝到緩存裏,再返回給調用函數。

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

Android培訓班 68 dex文件打開流程