Dex动态加载的C语言部分

本文详细分析了Android 4.0中Dex动态加载的C++部分,主要涉及内存加载过程。通过`Dalvik_dalvik_system_DexFile_openDexFile_bytearray`函数,从内存中读取字节数组并创建RawDexFile对象,再进行内存分配、文件内容拷贝和Dex文件打开操作。如果过程中出现异常,会抛出相应的运行时异常。
摘要由CSDN通过智能技术生成

 今天主要来分析Dex动态加载C++语言的部分(Android4.0)

 内存加载:

native代码:private static int openDexFile(byte[] fileContents) throws IOException

所对应的实现如下:

static void Dalvik_dalvik_system_DexFile_openDexFile_bytearray(const u4* args , JValue* pResult)
{
    ArrayObject* fileContentsObj = (ArrayObject*) args[0];
    u4 length;
    u1* pBytes;
    RawDexFile* pRawDexFile;
    DexOrJar* pDexOrJar = NULL;

    if (fileContentsObj == NULL) {
        dvmThrowNullPointerException("fileContents == null");
        RETURN_VOID();
    }

    length = fileContentsObj->length;
    pBytes = (u1*) malloc(length);

    if (pBytes == NULL) {
        dvmThrowRuntimeException("unable to allocate DEX memory");
        RETURN_VOID();
    }

    memcpy(pBytes, fileContentsObj->contents, length);

    if (dvmRawDexFileOpenArray(pBytes, length, &pRawDexFile) != 0) {
        LOGV("Unable to open in-memory DEX file");
        free(pBytes);
        dvmThrowRuntimeException("unable to open in-memory DEX file");
        RETURN_VOID();
    }

    LOGV("Opening in-memory DEX");
    pDexOrJar = (DexOrJar*) malloc(sizeof(DexOrJar));
    pDexOrJar->isDex = true;
    pDexOrJar->pRawDexFile = pRawDexFile;
    pDexOrJar->pDexMemory = pBytes;
    pDexOrJar->fileName = strdup("<memory>"); // Needs to be free()able.
    addToDexFileTable(pDexOrJar);

    RETURN_PTR(pDexOrJar);

}

首先来解释fileContentsObj这个对象的内容,从Java层传过来的byte[]类型的一个对象,当到达c++语言层的时候成了两个参数,args和pResult,然后把args这个数组中
的第一个元素直接转化成了ArrayObject对象,接下来显而易见,把这个元素的内容赋给了pBytes对象,那么这个总体的过程可以理解为一个Java层的byte[]类型的对象
转化为c++语言层的一个byte[]类型的对象;

接下来将是对dvmRawDexFileOpenArray(pBytes, length, &pRawDexFile)这个函数的分析,在分析之前,可以一起来看一下这个函数的三个参数,第一个参数和第二个
参数已经不用说了,就是一个byte[]类型的数组,以及这个数组中内容的长度,其实这个内容就是dex的字节流信息,第三个参数是一个RawDexFile的对象,这个对象的数据
结构是这样的:
struct RawDexFile {
    char*       cacheFileName;
    DvmDex*     pDvmDex;
};

这里又看到一个新的数据对象DvmDex,再来看一下这个数据结构:
struct DvmDex {
    DexFile*            pDexFile;
    const DexHeader*    pHeader;
    struct StringObject** pResStrings;
    struct ClassObject** pResClasses;
    struct Method**     pResMethods;
    struct Field**      pResFields;
    struct AtomicCache* pInterfaceCache;
    bool                isMappedReadOnly;
    MemMapping          memMap;
    pthread_mutex_t     modLock;
};

这里又看到一个新的数据对象DexFile,再来看一下这个数据结构:
struct DexFile {
    const DexOptHeader* pOptHeader;
 
    const DexHeader*    pHeader;
    const DexStringId*  pStringIds;
    const DexTypeId*    pTypeIds;
    const DexFieldId*   pFieldIds;
    const DexMethodId*  pMethodIds;
    const DexProtoId*   pProtoIds;
    const DexClassDef*  pClassDefs;
    const DexLink*      pLinkData;

    const DexClassLookup* pClassLookup;
    const void*         pRegisterMapPool;       // RegisterMapClassPool

    const u1*           baseAddr;

    int                 overhead;
}; 

这个数据结构如果了解dex文件格式的话,就对这里的一些对象比较清楚了,其实这个DvmDex数据结构中就保存了Dex文件的各个部分的一些相关内容,具体可以看一下Dex文件
的格式,这里不做多详细的介绍
现在回到那个方法,我们继续往下玩dvmRawDexFileOpenArray这个函数,
int dvmRawDexFileOpenArray(u1* pBytes, u4 length, RawDexFile** ppRawDexFile)
{
    DvmDex* pDvmDex = NULL;

    if (!dvmPrepareDexInMemory(pBytes, length, &pDvmDex)) {
        LOGD("Unable to open raw DEX from array");
        return -1;
    }
    assert(pDvmDex != NULL);

    *ppRawDexFile = (RawDexFile*) calloc(1, sizeof(RawDexFile));
    (*ppRawDexFile)->pDvmDex = pDvmDex;

    return 0;
}
我们可以看到进入这个函数的第一步就是建立了一个DvmDex类型的对象,并初始化为空,经过前面的分析,我们都应该有这个联系,这个pDvmDex对象不就是包含于RawDexFile
这个数据结构中的吗,再看最后第三行,(*ppRawDexFile)->pDvmDex = pDvmDex;,不用多解释,大家明白了这个赋值操作的含义,现在就来看看这个函数的中间部分到底
做了什么呢,还不是dvmPrepareDexInMemory(pBytes, length, &pDvmDex)这个东西惹的祸吗,我们继续进入其中作战,
bool dvmPrepareDexInMemory(u1* addr, size_t len, DvmDex** ppDvmDex)
{
    DexClassLookup* pClassLookup = NULL;
    if (!rewriteDex(addr, len, false, false, &pClassLookup, ppDvmDex)) {
        return false;
    }

    (*ppDvmDex)->pDexFile->pClassLookup = pClassLookup;

    return true;
}

先来看下DexClassLookup这个数据结构长啥模样吧,
struct DexClassLookup {
    int     size;                       
    int     numEntries;                 
    struct {
        u4      classDescriptorHash;    
        int     classDescriptorOffset;  
        int     classDefOffset;         
    } table[1];
};

其实很简单&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值