/* * Get the named method. */ Object* dvmGetDeclaredConstructorOrMethod(ClassObject* clazz, StringObject* nameObj, ArrayObject* args) { Object* result = NULL; DexStringCache targetDescriptorCache; char* name; const char* targetDescriptor; dexStringCacheInit(&targetDescriptorCache); name = dvmCreateCstrFromString(nameObj); createTargetDescriptor(args, &targetDescriptorCache); targetDescriptor = targetDescriptorCache.value; result = findConstructorOrMethodInArray(clazz->directMethodCount, clazz->directMethods, name, targetDescriptor); if (result == NULL) { result = findConstructorOrMethodInArray(clazz->virtualMethodCount, clazz->virtualMethods, name, targetDescriptor); } free(name); dexStringCacheRelease(&targetDescriptorCache); return result; }
int hprofStartup_StackFrame() { HashIter iter; /* Cache the string "<unknown>" for use when the source file is * unknown. */ hprofLookupStringId("<unknown>"); /* This will be called when a GC begins. */ for (dvmHashIterBegin(gStackFrameHashTable, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { StackFrameEntry *stackFrameEntry; const Method *method; /* Clear the 'live' bit at the start of the GC pass. */ stackFrameEntry = (StackFrameEntry *) dvmHashIterData(&iter); stackFrameEntry->live = 0; method = stackFrameEntry->frame.method; if (method == NULL) { continue; } /* Make sure the method name, descriptor, and source file are in * the string table, and that the method class is in the class * table. This is needed because strings and classes will be dumped * before stack frames. */ if (method->name) { hprofLookupStringId(method->name); } DexStringCache cache; const char* descriptor; dexStringCacheInit(&cache); descriptor = dexProtoGetMethodDescriptor(&method->prototype, &cache); hprofLookupStringId(descriptor); dexStringCacheRelease(&cache); const char* sourceFile = dvmGetMethodSourceFile(method); if (sourceFile) { hprofLookupStringId(sourceFile); } if (method->clazz) { hprofLookupClassId(method->clazz); } } return 0; }
/* * Create a new java/lang/reflect/Method object, using the contents of * "meth" to construct it. * * The spec doesn't specify the constructor. We're going to use the * one from our existing class libs: * * private Method(Class declaring, Class[] paramTypes, Class[] exceptTypes, * Class returnType, String name, int slot) * * The caller must call dvmReleaseTrackedAlloc() on the result. */ Object* dvmCreateReflectMethodObject(const Method* meth) { Object* result = NULL; ArrayObject* params = NULL; ArrayObject* exceptions = NULL; StringObject* nameObj = NULL; Object* methObj; ClassObject* returnType; DexStringCache mangle; char* cp; int slot, method_idx; if (dvmCheckException(dvmThreadSelf())) { ALOGW("WARNING: dvmCreateReflectMethodObject called with " "exception pending"); return NULL; } dexStringCacheInit(&mangle); /* parent should guarantee init so we don't have to check on every call */ assert(dvmIsClassInitialized(gDvm.classJavaLangReflectMethod)); methObj = dvmAllocObject(gDvm.classJavaLangReflectMethod, ALLOC_DEFAULT); if (methObj == NULL) goto bail; /* * Convert the signature string into an array of classes representing * the arguments, and a class for the return type. */ cp = dvmCopyDescriptorStringFromMethod(meth, &mangle); params = convertSignatureToClassArray(&cp, meth->clazz); if (params == NULL) goto bail; assert(*cp == ')'); cp++; returnType = convertSignaturePartToClass(&cp, meth->clazz); if (returnType == NULL) goto bail; /* * Create an array with one entry for every exception that the class * is declared to throw. */ exceptions = dvmGetMethodThrows(meth); if (dvmCheckException(dvmThreadSelf())) goto bail; /* method name */ nameObj = dvmCreateStringFromCstr(meth->name); if (nameObj == NULL) goto bail; slot = methodToSlot(meth); method_idx = dvmGetMethodIdx(meth); JValue unused; dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectMethod_init, methObj, &unused, meth->clazz, params, exceptions, returnType, nameObj, slot, method_idx); if (dvmCheckException(dvmThreadSelf())) { ALOGD("Method class init threw exception"); goto bail; } result = methObj; bail: dexStringCacheRelease(&mangle); if (result == NULL) { assert(dvmCheckException(dvmThreadSelf())); } dvmReleaseTrackedAlloc((Object*) nameObj, NULL); dvmReleaseTrackedAlloc((Object*) params, NULL); dvmReleaseTrackedAlloc((Object*) exceptions, NULL); if (result == NULL) dvmReleaseTrackedAlloc(methObj, NULL); return result; }
/* * Create a new java/lang/reflect/Constructor object, using the contents of * "meth" to construct it. * * The spec doesn't specify the constructor. We're going to use the * one from our existing class libs: * * private Constructor (Class declaringClass, Class[] ptypes, Class[] extypes, * int slot) */ static Object* createConstructorObject(Method* meth) { Object* result = NULL; ArrayObject* params = NULL; ArrayObject* exceptions = NULL; Object* consObj; DexStringCache mangle; char* cp; int slot, method_idx; dexStringCacheInit(&mangle); /* parent should guarantee init so we don't have to check on every call */ assert(dvmIsClassInitialized(gDvm.classJavaLangReflectConstructor)); consObj = dvmAllocObject(gDvm.classJavaLangReflectConstructor, ALLOC_DEFAULT); if (consObj == NULL) goto bail; /* * Convert the signature string into an array of classes representing * the arguments. */ cp = dvmCopyDescriptorStringFromMethod(meth, &mangle); params = convertSignatureToClassArray(&cp, meth->clazz); if (params == NULL) goto bail; assert(*cp == ')'); assert(*(cp+1) == 'V'); /* * Create an array with one entry for every exception that the class * is declared to throw. */ exceptions = dvmGetMethodThrows(meth); if (dvmCheckException(dvmThreadSelf())) goto bail; slot = methodToSlot(meth); method_idx = dvmGetMethodIdx(meth); JValue unused; dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectConstructor_init, consObj, &unused, meth->clazz, params, exceptions, slot, method_idx); if (dvmCheckException(dvmThreadSelf())) { ALOGD("Constructor class init threw exception"); goto bail; } result = consObj; bail: dexStringCacheRelease(&mangle); dvmReleaseTrackedAlloc((Object*) params, NULL); dvmReleaseTrackedAlloc((Object*) exceptions, NULL); if (result == NULL) { assert(dvmCheckException(dvmThreadSelf())); dvmReleaseTrackedAlloc(consObj, NULL); } /* caller must dvmReleaseTrackedAlloc(result) */ return result; }
int hprofDumpStackFrames(hprof_context_t *ctx) { HashIter iter; hprof_record_t *rec = &ctx->curRec; dvmHashTableLock(gStackFrameHashTable); for (dvmHashIterBegin(gStackFrameHashTable, &iter); !dvmHashIterDone(&iter); dvmHashIterNext(&iter)) { const StackFrameEntry *stackFrameEntry; const Method *method; int pc; const char *sourceFile; ClassObject *clazz; int lineNum; hprofStartNewRecord(ctx, HPROF_TAG_STACK_FRAME, HPROF_TIME); stackFrameEntry = (const StackFrameEntry *) dvmHashIterData(&iter); assert(stackFrameEntry != NULL); method = stackFrameEntry->frame.method; pc = stackFrameEntry->frame.pc; sourceFile = dvmGetMethodSourceFile(method); if (sourceFile == NULL) { sourceFile = "<unknown>"; lineNum = 0; } else { lineNum = dvmLineNumFromPC(method, pc); } clazz = (ClassObject *) hprofLookupClassId(method->clazz); /* STACK FRAME format: * * ID: ID for this stack frame * ID: ID for the method name * ID: ID for the method descriptor * ID: ID for the source file name * u4: class serial number * u4: line number, 0 = no line information * * We use the address of the stack frame as its ID. */ DexStringCache cache; const char* descriptor; dexStringCacheInit(&cache); descriptor = dexProtoGetMethodDescriptor(&method->prototype, &cache); hprofAddIdToRecord(rec, (u4) stackFrameEntry); hprofAddIdToRecord(rec, hprofLookupStringId(method->name)); hprofAddIdToRecord(rec, hprofLookupStringId(descriptor)); hprofAddIdToRecord(rec, hprofLookupStringId(sourceFile)); hprofAddU4ToRecord(rec, (u4) clazz->serialNumber); hprofAddU4ToRecord(rec, (u4) lineNum); dexStringCacheRelease(&cache); } dvmHashTableUnlock(gStackFrameHashTable); return 0; }