struct DexOrJar {
char* fileName;
bool isDex;
bool okayToFree;
RawDexFile* pRawDexFile;
JarFile* pJarFile;
u1* pDexMemory; // malloc()ed memory, if any
};
如果是dex文件就会调用dvmRawDexFileOpen填充RawDexFile结构,如果是jar文件就会调用dvmJarFileOpen填充JarFile。结构如下:
struct RawDexFile {
char* cacheFileName;
DvmDex* pDvmDex;
};
struct JarFile {
ZipArchive archive;
char* cacheFileName;
DvmDex* pDvmDex;
};
其中最重要的就是pDvmDex这个结构体。
struct DvmDex {
DexFile* pDexFile; //odex的信息
const DexHeader* pHeader; //dex文件头相关信息
struct StringObject** pResStrings; //字符串
struct ClassObject** pResClasses; //通过DexFile里的ClassDefItem构造出来的一个结构体(类信息)
struct Method** pResMethods; //通过Method_Item构造出来的结构体(方法信息)
struct Field** pResFields;
struct AtomicCache* pInterfaceCache;
bool isMappedReadOnly;
MemMapping memMap;
jobject dex_object;
pthread_mutex_t modLock;
};
DexFile结构体存储了odex文件的一些信息。
struct DexFile {
/* directly-mapped “opt” header */
const DexOptHeader* pOptHeader;
/* pointers to directly-mapped structs and arrays in base DEX */
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;
};
其中DexClassLookup结构体是用来方便快速查找某个类的一个hash表。
struct DexClassLookup {
int size; // total size, including “size”
int numEntries; // size of table[]; always power of 2
struct {
u4 classDescriptorHash; // class descriptor hash code
int classDescriptorOffset; // in bytes, from start of DEX
int classDefOffset; // in bytes, from start of DEX
} table[1];
};
关于DexClassLookup结构 可以参考:
http://blog.csdn.net/roland_sun/article/details/46877563
这篇文章。
然后再来看看Dalvik_dalvik_system_DexFile_defineClassNative方法是怎么找到类信息的。
代码地址:http://androidxref.com/4.4_r1/xref/dalvik/vm/native/dalvik_system_DexFile.cpp
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
static
void Dalvik_dalvik_system_DexFile_defineClassNative
(
const u4
* args,
JValue * pResult ) { StringObject * nameObj = (StringObject * ) args [ 0 ] ; Object * loader = ( Object * ) args [ 1 ] ; int cookie = args [ 2 ] ; ClassObject * clazz = NULL ; DexOrJar * pDexOrJar = (DexOrJar * ) cookie ; DvmDex * pDvmDex ; char * name ; char * descriptor ; name = dvmCreateCstrFromString (nameObj ) ; //把com.monkey.test 转成Lcom/monkey/test; descriptor = dvmDotToDescriptor (name ) ; ALOGV ( "--- Explicit class load '%s' l=%p c=0x%08x", descriptor, loader, cookie ) ; free (name ) ; if ( !validateCookie (cookie ) ) RETURN_VOID ( ) ; //获取pDvmDex if (pDexOrJar ->isDex ) pDvmDex = dvmGetRawDexFileDex (pDexOrJar ->pRawDexFile ) ; else pDvmDex = dvmGetJarFileDex (pDexOrJar ->pJarFile ) ; /* once we load something, we can't unmap the storage */ pDexOrJar ->okayToFree = false ; //获取ClassObject clazz = dvmDefineClass (pDvmDex, descriptor, loader ) ; Thread * self = dvmThreadSelf ( ) ; if (dvmCheckException (self ) ) { /* * If we threw a "class not found" exception, stifle it, since the * contract in the higher method says we simply return null if * the class is not found. */ Object * excep = dvmGetException (self ) ; if (strcmp (excep ->clazz ->descriptor, "Ljava/lang/ClassNotFoundException;" ) == 0 || strcmp (excep ->clazz ->descriptor, "Ljava/lang/NoClassDefFoundError;" ) == 0 ) { dvmClearException (self ) ; } clazz = NULL ; } free (descriptor ) ; RETURN_PTR (clazz ) ; } |
然后看里面的dvmDefineClass方法:
1
2 3 4 5 6 7 |
ClassObject
* dvmDefineClass
(DvmDex
* pDvmDex,
const
char
* descriptor,
Object * classLoader ) { assert (pDvmDex != NULL ) ; return findClassNoInit (descriptor, classLoader, pDvmDex ) ; } |
这里调用了findClassNoInit函数:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
static ClassObject
* findClassNoInit
(
const
char
* descriptor,
Object
* loader,
DvmDex * pDvmDex ) { Thread * self = dvmThreadSelf ( ) ; ClassObject * clazz ; .............. clazz = dvmLookupClass (descriptor, loader, true ) ; //判断当前的类是否已经加载 if (clazz == NULL ) { const DexClassDef * pClassDef ; if (pDvmDex == NULL ) { assert (loader == NULL ) ; /* shouldn't be here otherwise */ pDvmDex = searchBootPathForClass (descriptor, &pClassDef ) ; //如果pDvmDex为NULL,从系统缺省的库目录里加载 } else { pClassDef = dexFindClass (pDvmDex ->pDexFile, descriptor ) ; //从dex文件中找到目标类的classDefItem数据 } .............. /* found a match, try to load it */ clazz = loadClassFromDex (pDvmDex, pClassDef, loader ) ; //通过dex文件对象,目标类的ClassDefItem,classloader来加载目标类到内存中,最后会构造一个ClassObject结构 .............. dvmLockObject (self, ( Object * ) clazz ) ; if ( !dvmAddClassToHash (clazz ) ) { //加到hash_table的时候出错的一些处理 } } } struct ClassObject : Object { u4 instanceData [CLASS_FIELD_SLOTS ] ; const char * descriptor ; char * descriptorAlloc ; u4 accessFlags ; u4 serialNumber ; DvmDex * pDvmDex ; ClassStatus status ; ClassObject * verifyErrorClass ; u4 initThreadId ; size_t objectSize ; ClassObject * elementClass ; int arrayDim ; PrimitiveType primitiveType ; ClassObject * super ; Object * classLoader ; InitiatingLoaderList initiatingLoaderList ; int interfaceCount ; ClassObject ** interfaces ; int directMethodCount ; Method * directMethods ; int virtualMethodCount ; Method * virtualMethods ; int vtableCount ; Method ** vtable ; int iftableCount ; InterfaceEntry * iftable ; int ifviPoolCount ; int * ifviPool ; int ifieldCount ; int ifieldRefCount ; InstField * ifields ; u4 refOffsets ; const char * sourceFile ; int sfieldCount ; StaticField sfields [ 0 ] ; } ; |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
static ClassObject
* loadClassFromDex
(DvmDex
* pDvmDex,
const DexClassDef * pClassDef, Object * classLoader ) { ClassObject * result ; DexClassDataHeader header ; const u1 * pEncodedData ; const DexFile * pDexFile ; assert ( (pDvmDex != NULL ) && (pClassDef != NULL ) ) ; pDexFile = pDvmDex ->pDexFile ; if (gDvm. verboseClass ) { ALOGV ( "CLASS: loading '%s'...", dexGetClassDescriptor (pDexFile, pClassDef ) ) ; } pEncodedData = dexGetClassData (pDexFile, pClassDef ) ; //得到classDefItem里的ClassData if (pEncodedData != NULL ) { dexReadClassDataHeader ( &pEncodedData, &header ) ; //读取classDefItem的头信息 } else { // Provide an all-zeroes header for the rest of the loading. memset ( &header, 0, sizeof (header ) ) ; } result = loadClassFromDex0 (pDvmDex, pClassDef, &header, pEncodedData, classLoader ) ; //根据一系列类的数据,对ClassObject这个结构体的字段进行填充处理 if (gDvm. verboseClass && (result != NULL ) ) { ALOGI ( "[Loaded %s from DEX %p (cl=%p)]", result ->descriptor, pDvmDex, classLoader ) ; } return result ; } |
最后调用loadClassFromDex0填充ClassObject结构。
类加载完了,还有类的方法的加载:
上面的loadClassFromDex0函数里面会调用dexReadClassDataMethod来读取Method信息,
DEX_INLINE void dexReadClassDataMethod(const u1** pData, DexMethod* pMethod,
u4* lastIndex) {
u4 index = *lastIndex + readUnsignedLeb128(pData);
pMethod->accessFlags = readUnsignedLeb128(pData);
pMethod->codeOff = readUnsignedLeb128(pData);
pMethod->methodIdx = index;
*lastIndex = index;
}
然后通过函数
static void loadMethodFromDex(ClassObject* clazz, const DexMethod* pDexMethod, Method* meth)来根据methodid找到method信息。
pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
meth->name = dexStringById(pDexFile, pMethodId->nameIdx);
dexProtoSetFromMethodId(&meth->prototype, pDexFile, pMethodId);
meth->shorty = dexProtoGetShorty(&meth->prototype);
meth->accessFlags = pDexMethod->accessFlags;
meth->clazz = clazz;
meth->jniArgInfo = 0;
meth->registersSize = pDexCode->registersSize;
meth->insSize = pDexCode->insSize;
meth->outsSize = pDexCode->outsSize;
meth->insns = pDexCode->insns;
if (dvmIsNativeMethod(meth)) {
meth->nativeFunc = dvmResolveNativeMethod;
meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
}
本文链接:http://www.blogfshare.com/defineclassnative.html