/* 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(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 a static field reference. The DexFile format doesn't distinguish * between static and instance field references, so the "resolved" pointer * in the Dex struct will have the wrong type. We trivially cast it here. * * Causes the field's class to be initialized. */ StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; StaticField* resField; pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindStaticFieldHier(resClass, dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); if (resField == NULL) { dvmThrowNoSuchFieldError( dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); return NULL; } /* * If we're the first to resolve the field in which this class resides, * we need to do it now. Note that, if the field was inherited from * a superclass, it is not necessarily the same as "resClass". */ if (!dvmIsClassInitialized(resField->clazz) && !dvmInitClass(resField->clazz)) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } /* * If the class has been initialized, add a pointer to our data structure * so we don't have to jump through the hoops again. If it's still * initializing (i.e. this thread is executing <clinit>), don't do * the store, otherwise other threads could use the field without waiting * for class init to finish. */ if (dvmIsClassInitialized(resField->clazz)) { dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField); } else { LOGVV("--- not caching resolved field %s.%s (class init=%d/%d)", resField->clazz->descriptor, resField->name, dvmIsClassInitializing(resField->clazz), dvmIsClassInitialized(resField->clazz)); } return resField; }
/* * Resolve a static field reference. The DexFile format doesn't distinguish * between static and instance field references, so the "resolved" pointer * in the Dex struct will have the wrong type. We trivially cast it here. * * Causes the field's class to be initialized. */ StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) { DvmDex* pDvmDex = referrer->pDvmDex; ClassObject* resClass; const DexFieldId* pFieldId; StaticField* resField; pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx); /* * Find the field's class. */ resClass = dvmResolveClass(referrer, pFieldId->classIdx, false); if (resClass == NULL) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } resField = dvmFindStaticFieldHier(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; } /* * If we're the first to resolve the field in which this class resides, * we need to do it now. Note that, if the field was inherited from * a superclass, it is not necessarily the same as "resClass". */ if (!dvmIsClassInitialized(resField->field.clazz) && !dvmInitClass(resField->field.clazz)) { assert(dvmCheckException(dvmThreadSelf())); return NULL; } /* * 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, sfieldIdx, (Field*) resField); return resField; }
/* * 在当前的类或者父类中查找相匹配的静态字段,如果没有找到才返回值为NULL * */ StaticField* dvmFindStaticFieldHier(const ClassObject* clazz, const char* fieldName, const char* signature) { StaticField* pField; /* * Search for a match in the current class. */ pField = dvmFindStaticField(clazz, fieldName, signature); if (pField != NULL) return pField; /* * See if it's in any of our interfaces. We don't check interfaces * inherited from the superclass yet. * * (Note the set may have been stripped down because of redundancy with * the superclass; see notes in createIftable.) */ int i = 0; if (clazz->super != NULL) { assert(clazz->iftableCount >= clazz->super->iftableCount); i = clazz->super->iftableCount; } for ( ; i < clazz->iftableCount; i++) { ClassObject* iface = clazz->iftable[i].clazz; pField = dvmFindStaticField(iface, fieldName, signature); if (pField != NULL) return pField; } if (clazz->super != NULL) return dvmFindStaticFieldHier(clazz->super, fieldName, signature); else return NULL; }