/* returns the field structure corresponding to the profile entry * variable in the form: <signature> % <name> */ Field* getFieldFromProfileVar(const char* var, const ClassObject* clazz) { char* pos; char* sig; char* name; InstField* ifield; StaticField* sfield; Field* field = NULL; // TODO: Can we avoid the allocation if we replace the '%'? // Need to make sure there isn't a locking problem if that route // is taken. pos = index((char *)var, '%'); sig = strndup(var, pos-var); name = strdup(pos+1); /* Try both static and instance fields */ ifield = dvmFindInstanceFieldHier(clazz, name, sig); if (ifield != NULL) { field = (Field*) ifield; } else { sfield = dvmFindStaticFieldHier(clazz, name, sig); if (sfield != NULL) { field = (Field*) sfield; } } free(sig); free(name); return field; }
// Based on dvmResolveInstField/dvmResolveStaticField. static void preloadDexCachesResolveField(DvmDex* pDvmDex, uint32_t fieldIdx, bool instance) { Field* field = dvmDexGetResolvedField(pDvmDex, fieldIdx); if (field != NULL) { return; } const DexFile* pDexFile = pDvmDex->pDexFile; const DexFieldId* pFieldId = dexGetFieldId(pDexFile, fieldIdx); ClassObject* clazz = dvmDexGetResolvedClass(pDvmDex, pFieldId->classIdx); if (clazz == NULL) { return; } // Skip static fields for uninitialized classes because a filled // cache entry implies the class is initialized. if (!instance && !dvmIsClassInitialized(clazz)) { return; } const char* fieldName = dexStringById(pDexFile, pFieldId->nameIdx); const char* signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); if (instance) { field = dvmFindInstanceFieldHier(clazz, fieldName, signature); } else { field = dvmFindStaticFieldHier(clazz, fieldName, signature); } if (field == NULL) { return; } // ALOGI("VMRuntime.preloadDexCaches found field %s %s.%s", // signature, clazz->descriptor, fieldName); dvmDexSetResolvedField(pDvmDex, fieldIdx, field); }
/* * Resolve an instance field reference. * * Returns NULL and throws an exception on error (no such field, illegal * access). */ InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; InstField* resField; LOGVV("--- resolving field %u (referrer=%s cl=%p)", ifieldIdx, referrer->descriptor, referrer->classLoader); pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindInstanceFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowNoSuchFieldError( dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * Class must be initialized by now (unless verifier is buggy). We * could still be in the process of initializing it if the field * access is from a static initializer. */ assert(dvmIsClassInitialized(resField->clazz) || dvmIsClassInitializing(resField->clazz)); /* * The class is initialized (or initializing), the field has been * found. Add a pointer to our data structure so we don't have to * jump through the hoops again. * * Anything that uses the resolved table entry must have an instance * of the class, so any class init activity has already happened (or * been deliberately bypassed when <clinit> created an instance). * So it's always okay to update the table. */ dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField); LOGVV(" field %u is %s.%s", ifieldIdx, resField->clazz->descriptor, resField->name); return resField; }
/* * Resolve an instance field reference. * * Returns NULL and throws an exception on error (no such field, illegal * access). */ InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; InstField* resField; LOGVV("--- resolving field %u (referrer=%s cl=%p)\n", ifieldIdx, referrer->descriptor, referrer->classLoader); pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindInstanceFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowException("Ljava/lang/NoSuchFieldError;", dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * Class must be initialized by now (unless verifier is buggy). We * could still be in the process of initializing it if the field * access is from a static initializer. */ assert(dvmIsClassInitialized(resField->field.clazz) || dvmIsClassInitializing(resField->field.clazz)); /* * The class is initialized, the method has been found. Add a pointer * to our data structure so we don't have to jump through the hoops again. */ dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*)resField); LOGVV(" field %u is %s.%s\n", ifieldIdx, resField->field.clazz->descriptor, resField->field.name); return resField; }
/* * 在当前的类或者它的父类中查找所匹配的实例字段 * * 通过接口去查找不是必要的,因为接口字段是固有的 (public/static/final) */ InstField* dvmFindInstanceFieldHier(const ClassObject* clazz, const char* fieldName, const char* signature) { InstField* pField; /* * Search for a match in the current class. */ pField = dvmFindInstanceField(clazz, fieldName, signature); if (pField != NULL) return pField; if (clazz->super != NULL) return dvmFindInstanceFieldHier(clazz->super, fieldName, signature); else return NULL; }