/* * static Class findLoadedClass(ClassLoader cl, String name) */ static void Dalvik_java_lang_VMClassLoader_findLoadedClass(const u4* args, JValue* pResult) { Object* loader = (Object*) args[0]; StringObject* nameObj = (StringObject*) args[1]; ClassObject* clazz = NULL; char* name = NULL; char* descriptor = NULL; if (nameObj == NULL) { dvmThrowException("Ljava/lang/NullPointerException;", NULL); goto bail; } /* * Get a UTF-8 copy of the string, and convert dots to slashes. */ name = dvmCreateCstrFromString(nameObj); if (name == NULL) goto bail; descriptor = dvmDotToDescriptor(name); if (descriptor == NULL) goto bail; clazz = dvmLookupClass(descriptor, loader, false); LOGVV("look: %s ldr=%p --> %p\n", descriptor, loader, clazz); bail: free(name); free(descriptor); RETURN_PTR(clazz); }
/* * Induce verification on all classes loaded from this DEX file as part * of pre-verification and optimization. This is never called from a * normally running VM. * * Returns "true" when all classes have been processed. */ bool dvmVerifyAllClasses(DexFile* pDexFile) { u4 count = pDexFile->pHeader->classDefsSize; u4 idx; assert(gDvm.optimizing); if (gDvm.classVerifyMode == VERIFY_MODE_NONE) { LOGV("+++ verification is disabled, skipping all classes\n"); return true; } if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE && gDvm.optimizingBootstrapClass) { LOGV("+++ verification disabled for bootstrap classes\n"); return true; } for (idx = 0; idx < count; idx++) { const DexClassDef* pClassDef; const char* classDescriptor; ClassObject* clazz; pClassDef = dexGetClassDef(pDexFile, idx); classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); /* all classes are loaded into the bootstrap class loader */ clazz = dvmLookupClass(classDescriptor, NULL, false); if (clazz != NULL) { if (clazz->pDvmDex->pDexFile != pDexFile) { LOGD("DexOpt: not verifying '%s': multiple definitions\n", classDescriptor); } else { if (dvmVerifyClass(clazz, VERIFY_DEFAULT)) { assert((clazz->accessFlags & JAVA_FLAGS_MASK) == pClassDef->accessFlags); ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED; } /* keep going even if one fails */ } } else { LOGV("DexOpt: +++ not verifying '%s'\n", classDescriptor); } } return true; }
/* * Verify and/or optimize all classes that were successfully loaded from * this DEX file. */ static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, bool doOpt) { u4 count = pDexFile->pHeader->classDefsSize; u4 idx; /* * Create a data structure for use by the bytecode optimizer. We * stuff it into a global so we don't have to pass it around as * a function argument. * * We could create this at VM startup, but there's no need to do so * unless we're optimizing, which means we're in dexopt, and we're * only going to call here once. */ if (doOpt) { gDvm.inlineSubs = dvmCreateInlineSubsTable(); if (gDvm.inlineSubs == NULL) return; } for (idx = 0; idx < count; idx++) { const DexClassDef* pClassDef; const char* classDescriptor; ClassObject* clazz; pClassDef = dexGetClassDef(pDexFile, idx); classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); /* all classes are loaded into the bootstrap class loader */ clazz = dvmLookupClass(classDescriptor, NULL, false); if (clazz != NULL) { verifyAndOptimizeClass(pDexFile, clazz, pClassDef, doVerify, doOpt); } else { // TODO: log when in verbose mode LOGV("DexOpt: not optimizing unavailable class '%s'\n", classDescriptor); } } if (gDvm.inlineSubs != NULL) { dvmFreeInlineSubsTable(gDvm.inlineSubs); gDvm.inlineSubs = NULL; } }
// Based on dvmResolveClass. static void preloadDexCachesResolveType(DvmDex* pDvmDex, uint32_t typeIdx) { ClassObject* clazz = dvmDexGetResolvedClass(pDvmDex, typeIdx); if (clazz != NULL) { return; } const DexFile* pDexFile = pDvmDex->pDexFile; const char* className = dexStringByTypeIdx(pDexFile, typeIdx); if (className[0] != '\0' && className[1] == '\0') { /* primitive type */ clazz = dvmFindPrimitiveClass(className[0]); } else { clazz = dvmLookupClass(className, NULL, true); } if (clazz == NULL) { return; } // Skip uninitialized classes because filled cache entry implies it is initialized. if (!dvmIsClassInitialized(clazz)) { // ALOGI("VMRuntime.preloadDexCaches uninitialized clazz=%s", className); return; } // ALOGI("VMRuntime.preloadDexCaches found clazz=%s", className); dvmDexSetResolvedClass(pDvmDex, typeIdx, clazz); }
/* * static boolean cacheRegisterMap(String classAndMethodDescr) * * If the specified class is loaded, and the named method exists, ensure * that the method's register map is ready for use. If the class/method * cannot be found, nothing happens. * * This can improve the zygote's sharing of compressed register maps. Do * this after class preloading. * * Returns true if the register map is cached and ready, either as a result * of this call or earlier activity. Returns false if the class isn't loaded, * if the method couldn't be found, or if the method has no register map. * * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.) */ static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args, JValue* pResult) { StringObject* classAndMethodDescStr = (StringObject*) args[0]; ClassObject* clazz; bool result = false; if (classAndMethodDescStr == NULL) { dvmThrowNullPointerException("classAndMethodDesc == null"); RETURN_VOID(); } char* classAndMethodDesc = NULL; /* * Pick the string apart. We have a local copy, so just modify it * in place. */ classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr); char* methodName = strchr(classAndMethodDesc, '.'); if (methodName == NULL) { dvmThrowRuntimeException("method name not found in string"); RETURN_VOID(); } *methodName++ = '\0'; char* methodDescr = strchr(methodName, ':'); if (methodDescr == NULL) { dvmThrowRuntimeException("method descriptor not found in string"); RETURN_VOID(); } *methodDescr++ = '\0'; //ALOGD("GOT: %s %s %s", classAndMethodDesc, methodName, methodDescr); /* * Find the class, but only if it's already loaded. */ clazz = dvmLookupClass(classAndMethodDesc, NULL, false); if (clazz == NULL) { ALOGD("Class %s not found in bootstrap loader", classAndMethodDesc); goto bail; } Method* method; /* * Find the method, which could be virtual or direct, defined directly * or inherited. */ if (methodName[0] == '<') { /* * Constructor or class initializer. Only need to examine the * "direct" list, and don't need to search up the class hierarchy. */ method = dvmFindDirectMethodByDescriptor(clazz, methodName, methodDescr); } else { /* * Try both lists, and scan up the tree. */ method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName, methodDescr); if (method == NULL) { method = dvmFindDirectMethodHierByDescriptor(clazz, methodName, methodDescr); } } if (method != NULL) { /* * Got it. See if there's a register map here. */ const RegisterMap* pMap; pMap = dvmGetExpandedRegisterMap(method); if (pMap == NULL) { ALOGV("No map for %s.%s %s", classAndMethodDesc, methodName, methodDescr); } else { ALOGV("Found map %s.%s %s", classAndMethodDesc, methodName, methodDescr); result = true; } } else { ALOGV("Unable to find %s.%s %s", classAndMethodDesc, methodName, methodDescr); } bail: free(classAndMethodDesc); RETURN_BOOLEAN(result); }