/* * 从指定的DEX文件中加载一个类,使用类加载器去初始化一个类对象 */ static void Dalvik_dalvik_system_DexFile_defineClass(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); descriptor = dvmDotToDescriptor(name); ALOGV("--- Explicit class load '%s' l=%p c=0x%08x", descriptor, loader, cookie); free(name); if (!validateCookie(cookie)) RETURN_VOID(); 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; 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); }
/* * private static String[] getClassNameList(int cookie) * * Returns a String array that holds the names of all classes in the * specified DEX file. */ static void Dalvik_dalvik_system_DexFile_getClassNameList(const u4* args, JValue* pResult) { int cookie = args[0]; DexOrJar* pDexOrJar = (DexOrJar*) cookie; DvmDex* pDvmDex; DexFile* pDexFile; ArrayObject* stringArray; Thread* self = dvmThreadSelf(); if (!validateCookie(cookie)) RETURN_VOID(); if (pDexOrJar->isDex) pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile); else pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile); assert(pDvmDex != NULL); pDexFile = pDvmDex->pDexFile; int count = pDexFile->pHeader->classDefsSize; stringArray = dvmAllocObjectArray(gDvm.classJavaLangString, count, ALLOC_DEFAULT); if (stringArray == NULL) { /* probably OOM */ ALOGD("Failed allocating array of %d strings\n", count); assert(dvmCheckException(self)); RETURN_VOID(); } int i; for (i = 0; i < count; i++) { const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i); const char* descriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); char* className = dvmDescriptorToDot(descriptor); StringObject* str = dvmCreateStringFromCstr(className); dvmSetObjectArrayElement(stringArray, i, (Object *)str); dvmReleaseTrackedAlloc((Object *)str, self); free(className); } dvmReleaseTrackedAlloc((Object*)stringArray, self); RETURN_PTR(stringArray); }
/* * Get the SHA-1 signature. */ static const u1* getSignature(const ClassPathEntry* cpe) { DvmDex* pDvmDex; switch (cpe->kind) { case kCpeJar: pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr); break; case kCpeDex: pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr); break; default: LOGE("unexpected cpe kind %d\n", cpe->kind); dvmAbort(); pDvmDex = NULL; // make gcc happy } assert(pDvmDex != NULL); return pDvmDex->pDexFile->pHeader->signature; }
/* * private static String[] getClassNameList(int cookie) * * Returns a String array that holds the names of all classes in the * specified DEX file. */ static void Dalvik_dalvik_system_DexFile_getClassNameList(const u4* args, JValue* pResult) { int cookie = args[0]; DexOrJar* pDexOrJar = (DexOrJar*) cookie; DvmDex* pDvmDex; DexFile* pDexFile; ArrayObject* stringArray; if (!validateCookie(cookie)) RETURN_VOID(); if (pDexOrJar->isDex) pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile); else pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile); assert(pDvmDex != NULL); pDexFile = pDvmDex->pDexFile; int count = pDexFile->pHeader->classDefsSize; stringArray = dvmAllocObjectArray(gDvm.classJavaLangString, count, ALLOC_DEFAULT); if (stringArray == NULL) RETURN_VOID(); // should be an OOM pending StringObject** contents = (StringObject**) stringArray->contents; int i; for (i = 0; i < count; i++) { const DexClassDef* pClassDef = dexGetClassDef(pDexFile, i); const char* descriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); char* className = dvmDescriptorToDot(descriptor); contents[i] = dvmCreateStringFromCstr(className, ALLOC_DEFAULT); dvmReleaseTrackedAlloc((Object*) contents[i], NULL); free(className); } dvmReleaseTrackedAlloc((Object*)stringArray, NULL); RETURN_PTR(stringArray); }
/* * private static Class defineClass(String name, ClassLoader loader, * int cookie, ProtectionDomain pd) * * Load a class from a DEX file. This is roughly equivalent to defineClass() * in a regular VM -- it's invoked by the class loader to cause the * creation of a specific class. The difference is that the search for and * reading of the bytes is done within the VM. * * The class name is a "binary name", e.g. "java.lang.String". * * Returns a null pointer with no exception if the class was not found. * Throws an exception on other failures. */ static void Dalvik_dalvik_system_DexFile_defineClass(const u4* args, JValue* pResult) { StringObject* nameObj = (StringObject*) args[0]; Object* loader = (Object*) args[1]; int cookie = args[2]; Object* pd = (Object*) args[3]; ClassObject* clazz = NULL; DexOrJar* pDexOrJar = (DexOrJar*) cookie; DvmDex* pDvmDex; char* name; char* descriptor; name = dvmCreateCstrFromString(nameObj); descriptor = dvmDotToDescriptor(name); LOGV("--- Explicit class load '%s' 0x%08x\n", descriptor, cookie); free(name); if (!validateCookie(cookie)) RETURN_VOID(); 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; 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; } /* * Set the ProtectionDomain -- do we need this to happen before we * link the class and make it available? If so, we need to pass it * through dvmDefineClass (and figure out some other * stuff, like where it comes from for bootstrap classes). */ if (clazz != NULL) { //LOGI("SETTING pd '%s' to %p\n", clazz->descriptor, pd); dvmSetFieldObject((Object*) clazz, gDvm.offJavaLangClass_pd, pd); } free(descriptor); RETURN_PTR(clazz); }