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

Dalvik_dalvik_system_DexFile详解
本文深入解析了Dalvik虚拟机中Dalvik_dalvik_system_DexFile函数的工作原理,包括如何打开Dex文件、处理异常、转换字符串、加载Dex文件到缓存,以及如何通过HASH表进行快速查找。

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

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

               

从上面可知调用函数Dalvik_dalvik_system_DexFile_openDexFile来打开Dex文件,这个函数的源码如下:

staticvoid Dalvik_dalvik_system_DexFile_openDexFile(const u4* args,

   JValue* pResult)

{

   StringObject* sourceNameObj =(StringObject*) args[0];

这行是输入的Jar或Dex文件名参数。


   StringObject* outputNameObj =(StringObject*) args[1];

这行是输出的文件名参数。


   int flags = args[2];

这行是处理的标示。


   DexOrJar* pDexOrJar = NULL;

   JarFile* pJarFile;

   RawDexFile* pRawDexFile;

   char* sourceName;

   char* outputName;


   if (sourceNameObj == NULL) {

       dvmThrowException("Ljava/lang/NullPointerException;",NULL);

       RETURN_VOID();

    }

这段代码是当输入文件名称为空对象时,就抛出异常。



   sourceName =dvmCreateCstrFromString(sourceNameObj);

这行代码调用函数dvmCreateCstrFromString把java字符串转换C字符串,由于Java对象表示的字符串并不能立即就使用到C语言里,所以需要转换才能使用。


   if (outputNameObj != NULL)

       outputName =dvmCreateCstrFromString(outputNameObj);

   else

       outputName = NULL;

这段代码是同样把输出字符串转换C字符串。



   /*

    * We have to deal with the possibility thatsomebody might try to

    * open one of our bootstrap class DEXfiles.  The set of dependencies

    * will be different, and hence the resultsof optimization might be

    * different, which means we'd actually needto have two versions of

    * the optimized DEX: one that only knowsabout part of the boot class

    * path, and one that knows about everythingin it.  The latter might

    * optimize field/method accesses based on aclass that appeared later

    * in the class path.

    *

    * We can't let the user-defined classloader open it and start using

    * the classes, since the optimized form ofthe code skips some of

    * the method and field resolution that wewould ordinarily do, and

    * we'd have the wrong semantics.

    *

    * We have to reject attempts to manuallyopen a DEX file from the boot

    * class path.  The easiest way to do thisis by filename, which works

    * out because variations in name (e.g."/system/framework/./ext.jar")

    * result in us hitting a differentdalvik-cache entry.  It's also fine

    * if the caller specifies their own outputfile.

    */

   if(dvmClassPathContains(gDvm.bootClassPath, sourceName)) {

       LOGW("Refusing to reopen boot DEX'%s'\n", sourceName);

       dvmThrowException("Ljava/io/IOException;",

           "Re-opening BOOTCLASSPATH DEXfiles is not allowed");

       free(sourceName);

       RETURN_VOID();

    }

这段代码是判断用户是否加载系统目录下面的Dex文件,如果加载就要拒绝这样的操作,因为系统启动时已经加载了一份这样的优化代码,没有必要再次加载一次。



   /*

    * Try to open it directly as a DEX.  Ifthat fails, try it as a Zip

    * with a "classes.dex" inside.

    */

   if (dvmRawDexFileOpen(sourceName,outputName, &pRawDexFile, false) == 0) {

       LOGV("Opening DEX file '%s'(DEX)\n", sourceName);


       pDexOrJar = (DexOrJar*)malloc(sizeof(DexOrJar));

       pDexOrJar->isDex = true;

       pDexOrJar->pRawDexFile = pRawDexFile;

这段代码是尝试加载Dex文件,但基本不存在直接加Dex文件的情况,因此在函数dvmRawDexFileOpen还是空函数,没有实际的内容。



    }else if (dvmJarFileOpen(sourceName, outputName, &pJarFile, false)== 0) {

       LOGV("Opening DEX file '%s'(Jar)\n", sourceName);


       pDexOrJar = (DexOrJar*)malloc(sizeof(DexOrJar));

       pDexOrJar->isDex = false;

       pDexOrJar->pJarFile = pJarFile;

这段代码是加载Jar文件,就是从这里加载Dex文件到缓存里。


    }else {

       LOGV("Unable to open DEX file'%s'\n", sourceName);

       dvmThrowException("Ljava/io/IOException;","unable to open DEX file");

    }



   if (pDexOrJar != NULL) {

       pDexOrJar->fileName = sourceName;

这行代码保存文件名称到Dex文件对象里。


       /* add to hash table */

       u4 hash = dvmComputeUtf8Hash(sourceName);

这行代码通过文件名称计算HASH串,加速对文件的查找速度。


       void* result;

       dvmHashTableLock(gDvm.userDexFiles);

       result =dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,

                   hashcmpDexOrJar, true);

       dvmHashTableUnlock(gDvm.userDexFiles);

这段代码添加HASH表里,以便后面查找使用。


       if (result != pDexOrJar) {

           LOGE("Pointer has already beenadded?\n");

           dvmAbort();

       }


       pDexOrJar->okayToFree = true;

    }else

       free(sourceName);


   RETURN_PTR(pDexOrJar);

这行代码返回打开的文件对象。


}


这个函数是通过JAVA调用时输入Dex文件名称,然后加载Dex文件,最后把这个文件名称放到HASH表里,然后返回打开的对象。

           

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值