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

本文深入解析了DVM如何通过dvmJarFileOpen函数找到并加载classes.dex文件到内存的过程,包括查找优化后的Dex文件、从压缩包中提取Dex文件、优化Dex文件及缓存管理等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

在上面的函数里,提到使用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文件,读取出来,并进行分析,然后拷贝到缓存里,再返回给调用函数。

           

给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值