/* * Create some "stock" exceptions. These can be thrown when the system is * too screwed up to allocate and initialize anything, or when we don't * need a meaningful stack trace. * * We can't do this during the initial startup because we need to execute * the constructors. */ bool dvmCreateStockExceptions() { /* * Pre-allocate some throwables. These need to be explicitly added * to the GC's root set (see dvmHeapMarkRootSet()). */ gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;", "[memory exhausted]"); dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL); gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;", "[pre-allocated]"); dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL); gDvm.noClassDefFoundErrorObj = createStockException("Ljava/lang/NoClassDefFoundError;", "[generic]"); dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL); if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL || gDvm.noClassDefFoundErrorObj == NULL) { LOGW("Unable to create stock exceptions"); return false; } return true; }
/* * Get an array with all constructors declared by a class. */ ArrayObject* dvmGetDeclaredConstructors(ClassObject* clazz, bool publicOnly) { if (!dvmIsClassInitialized(gDvm.classJavaLangReflectConstructor)) dvmInitClass(gDvm.classJavaLangReflectConstructor); /* * Ordinarily we init the class the first time we resolve a method. * We're bypassing the normal resolution mechanism, so we init it here. */ if (!dvmIsClassInitialized(clazz)) dvmInitClass(clazz); /* * Count up the #of relevant methods. */ size_t count = 0; for (int i = 0; i < clazz->directMethodCount; ++i) { Method* meth = &clazz->directMethods[i]; if ((!publicOnly || dvmIsPublicMethod(meth)) && dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth)) { count++; } } /* * Create an array of Constructor objects. */ ClassObject* arrayClass = gDvm.classJavaLangReflectConstructorArray; ArrayObject* ctorArray = dvmAllocArrayByClass(arrayClass, count, ALLOC_DEFAULT); if (ctorArray == NULL) return NULL; /* * Fill out the array. */ size_t ctorObjCount = 0; for (int i = 0; i < clazz->directMethodCount; ++i) { Method* meth = &clazz->directMethods[i]; if ((!publicOnly || dvmIsPublicMethod(meth)) && dvmIsConstructorMethod(meth) && !dvmIsStaticMethod(meth)) { Object* ctorObj = createConstructorObject(meth); if (ctorObj == NULL) { dvmReleaseTrackedAlloc((Object*) ctorArray, NULL); return NULL; } dvmSetObjectArrayElement(ctorArray, ctorObjCount, ctorObj); ++ctorObjCount; dvmReleaseTrackedAlloc(ctorObj, NULL); } } assert(ctorObjCount == ctorArray->length); /* caller must call dvmReleaseTrackedAlloc */ return ctorArray; }
/* * Create a "stock instance" of an exception class. */ static Object* createStockException(const char* descriptor, const char* msg) { Thread* self = dvmThreadSelf(); StringObject* msgStr = NULL; ClassObject* clazz; Method* init; Object* obj; /* find class, initialize if necessary */ clazz = dvmFindSystemClass(descriptor); if (clazz == NULL) { LOGE("Unable to find %s", descriptor); return NULL; } init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "(Ljava/lang/String;)V"); if (init == NULL) { LOGE("Unable to find String-arg constructor for %s", descriptor); return NULL; } obj = dvmAllocObject(clazz, ALLOC_DEFAULT); if (obj == NULL) return NULL; if (msg == NULL) { msgStr = NULL; } else { msgStr = dvmCreateStringFromCstr(msg); if (msgStr == NULL) { LOGW("Could not allocate message string \"%s\"", msg); dvmReleaseTrackedAlloc(obj, self); return NULL; } } JValue unused; dvmCallMethod(self, init, obj, &unused, msgStr); if (dvmCheckException(self)) { dvmReleaseTrackedAlloc((Object*) msgStr, self); dvmReleaseTrackedAlloc(obj, self); return NULL; } dvmReleaseTrackedAlloc((Object*) msgStr, self); // okay if msgStr NULL return obj; }
java_lang_String_ap fastiva_Dalvik_dalvik_system_VMRuntime_properties(dalvik_system_VMRuntime_p self) { #endif ArrayObject* result = dvmCreateStringArray(*gDvm.properties); dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf()); RETURN_PTR((java_lang_String_ap)result); }
java_lang_String_p fastiva_Dalvik_java_lang_System_mapLibraryName(java_lang_String_p nameObj) { #endif StringObject* result = NULL; char* name; char* mappedName; if (nameObj == NULL) { dvmThrowNullPointerException("userLibName == null"); THROW_V(); } name = dvmCreateCstrFromString(nameObj); #ifdef _DEBUG assert(strstr(name, "cfb") == NULL); #endif mappedName = dvmCreateSystemLibraryName(name); if (mappedName != NULL) { result = dvmCreateStringFromCstr(mappedName); dvmReleaseTrackedAlloc((Object*) result, NULL); } free(name); free(mappedName); RETURN_PTR((java_lang_String_p)result); }
static void Dalvik_dalvik_system_VMRuntime_properties(const u4* args, JValue* pResult) { ArrayObject* result = dvmCreateStringArray(*gDvm.properties); dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf()); RETURN_PTR(result); }
java_lang_Object_p fastiva_Dalvik_dalvik_system_VMRuntime_newNonMovableArray(dalvik_system_VMRuntime_p self, java_lang_Class_p elementClass, jint length) { #endif if (elementClass == NULL) { dvmThrowNullPointerException("elementClass == null"); THROW_V(); } if (length < 0) { dvmThrowNegativeArraySizeException(length); THROW_V(); } // TODO: right now, we don't have a copying collector, so there's no need // to do anything special here, but we ought to pass the non-movability // through to the allocator. ClassObject* arrayClass = dvmFindArrayClassForElement(elementClass); ArrayObject* newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_NON_MOVING); if (newArray == NULL) { assert(dvmCheckException(dvmThreadSelf())); THROW_V(); } dvmReleaseTrackedAlloc((Object*) newArray, NULL); RETURN_PTR(newArray); }
static void Dalvik_dalvik_system_VMRuntime_newNonMovableArray(const u4* args, JValue* pResult) { ClassObject* elementClass = (ClassObject*) args[1]; int length = args[2]; if (elementClass == NULL) { dvmThrowNullPointerException("elementClass == null"); RETURN_VOID(); } if (length < 0) { dvmThrowNegativeArraySizeException(length); RETURN_VOID(); } // TODO: right now, we don't have a copying collector, so there's no need // to do anything special here, but we ought to pass the non-movability // through to the allocator. ClassObject* arrayClass = dvmFindArrayClassForElement(elementClass); ArrayObject* newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_NON_MOVING); if (newArray == NULL) { assert(dvmCheckException(dvmThreadSelf())); RETURN_VOID(); } dvmReleaseTrackedAlloc((Object*) newArray, NULL); RETURN_PTR(newArray); }
/* * private Object getField(Object o, Class declaringClass, Class type, * int slot, boolean noAccessCheck) * * Primitive types need to be boxed. */ static void Dalvik_java_lang_reflect_Field_getField(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] Object* obj = (Object*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ClassObject* fieldType = (ClassObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); JValue value; const JValue* fieldPtr; DataObject* result; //dvmDumpClass(obj->clazz, kDumpClassFullDetail); /* get a pointer to the field's data; performs access checks */ fieldPtr = getFieldDataAddr(obj, declaringClass, slot, false,noAccessCheck); if (fieldPtr == NULL) RETURN_VOID(); /* copy 4 or 8 bytes out */ if (fieldType->primitiveType == PRIM_LONG || fieldType->primitiveType == PRIM_DOUBLE) { value.j = fieldPtr->j; } else { value.i = fieldPtr->i; } result = dvmWrapPrimitive(value, fieldType); dvmReleaseTrackedAlloc((Object*) result, NULL); RETURN_PTR(result); }
/* * Create a new java.lang.reflect.Field object from "field". * * The Field spec doesn't specify the constructor. We're going to use the * one from our existing class libs: * * private Field(Class declaringClass, Class type, String name, int slot) */ static Object* createFieldObject(Field* field, const ClassObject* clazz) { Object* result = NULL; Object* fieldObj = NULL; StringObject* nameObj = NULL; ClassObject* type; char* mangle; char* cp; int slot, field_idx; assert(dvmIsClassInitialized(gDvm.classJavaLangReflectField)); fieldObj = dvmAllocObject(gDvm.classJavaLangReflectField, ALLOC_DEFAULT); if (fieldObj == NULL) goto bail; cp = mangle = strdup(field->signature); type = convertSignaturePartToClass(&cp, clazz); free(mangle); if (type == NULL) goto bail; nameObj = dvmCreateStringFromCstr(field->name); if (nameObj == NULL) goto bail; slot = fieldToSlot(field, clazz); field_idx = dvmGetFieldIdx(field); JValue unused; dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectField_init, fieldObj, &unused, clazz, type, nameObj, slot, field_idx); if (dvmCheckException(dvmThreadSelf())) { ALOGD("Field class init threw exception"); goto bail; } result = fieldObj; bail: dvmReleaseTrackedAlloc((Object*) nameObj, NULL); if (result == NULL) dvmReleaseTrackedAlloc((Object*) fieldObj, NULL); /* caller must dvmReleaseTrackedAlloc(result) */ return result; }
/* * 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); }
/* * Convert an array of char* into a String[]. * * Returns NULL on failure, with an exception raised. */ static ArrayObject* convertStringArray(char** strings, size_t count) { Thread* self = dvmThreadSelf(); /* * Allocate an array to hold the String objects. */ ClassObject* stringArrayClass = dvmFindArrayClass("[Ljava/lang/String;", NULL); if (stringArrayClass == NULL) { /* shouldn't happen */ LOGE("Unable to find [Ljava/lang/String;\n"); dvmAbort(); } ArrayObject* stringArray = dvmAllocArrayByClass(stringArrayClass, count, ALLOC_DEFAULT); if (stringArray == NULL) { /* probably OOM */ LOGD("Failed allocating array of %d strings\n", count); assert(dvmCheckException(self)); return NULL; } /* * Create the individual String objects and add them to the array. */ size_t i; for (i = 0; i < count; i++) { Object *str = (Object *)dvmCreateStringFromCstr(strings[i]); if (str == NULL) { /* probably OOM; drop out now */ assert(dvmCheckException(self)); dvmReleaseTrackedAlloc((Object*)stringArray, self); return NULL; } dvmSetObjectArrayElement(stringArray, i, str); /* stored in tracked array, okay to release */ dvmReleaseTrackedAlloc(str, self); } dvmReleaseTrackedAlloc((Object*)stringArray, self); return stringArray; }
/* * public static byte[] getThreadStats() * * Get a buffer full of thread info. */ static void Dalvik_org_apache_harmony_dalvik_ddmc_DdmVmInternal_getThreadStats( const u4* args, JValue* pResult) { UNUSED_PARAMETER(args); ArrayObject* result = dvmDdmGenerateThreadStats(); dvmReleaseTrackedAlloc((Object*) result, NULL); RETURN_PTR(result); }
/* * private Object internalClone() * * Implements most of Object.clone(). */ static void Dalvik_java_lang_Object_internalClone(const u4* args, JValue* pResult) { Object* thisPtr = (Object*) args[0]; Object* clone = dvmCloneObject(thisPtr); dvmReleaseTrackedAlloc(clone, NULL); RETURN_PTR(clone); }
/* * private static Object[] getClassSignatureAnnotation(Class clazz) * * Return the Signature annotation for the specified class. Equivalent to * Class.getSignatureAnnotation(), but available to java.lang.reflect. */ static void Dalvik_java_lang_reflect_AccessibleObject_getClassSignatureAnnotation( const u4* args, JValue* pResult) { ClassObject* clazz = (ClassObject*) args[0]; ArrayObject* arr = dvmGetClassSignatureAnnotation(clazz); dvmReleaseTrackedAlloc((Object*) arr, NULL); RETURN_PTR(arr); }
/* * public static byte[] getRecentAllocations() * * Fill a buffer with data on recent heap allocations. */ static void Dalvik_org_apache_harmony_dalvik_ddmc_DdmVmInternal_getRecentAllocations( const u4* args, JValue* pResult) { ArrayObject* data; data = dvmDdmGetRecentAllocations(); dvmReleaseTrackedAlloc((Object*) data, NULL); RETURN_PTR(data); }
/* * Wrap the now-pending exception in a different exception. This is useful * for reflection stuff that wants to hand a checked exception back from a * method that doesn't declare it. * * If something fails, an (unchecked) exception related to that failure * will be pending instead. */ void dvmWrapException(const char* newExcepStr) { Thread* self = dvmThreadSelf(); Object* origExcep; ClassObject* iteClass; origExcep = dvmGetException(self); dvmAddTrackedAlloc(origExcep, self); // don't let the GC free it dvmClearException(self); // clear before class lookup iteClass = dvmFindSystemClass(newExcepStr); if (iteClass != NULL) { Object* iteExcep; Method* initMethod; iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT); if (iteExcep != NULL) { initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>", "(Ljava/lang/Throwable;)V"); if (initMethod != NULL) { JValue unused; dvmCallMethod(self, initMethod, iteExcep, &unused, origExcep); /* if <init> succeeded, replace the old exception */ if (!dvmCheckException(self)) dvmSetException(self, iteExcep); } dvmReleaseTrackedAlloc(iteExcep, NULL); /* if initMethod doesn't exist, or failed... */ if (!dvmCheckException(self)) dvmSetException(self, origExcep); } else { /* leave OutOfMemoryError pending */ } } else { /* leave ClassNotFoundException pending */ } assert(dvmCheckException(self)); dvmReleaseTrackedAlloc(origExcep, self); }
/* * static String[] getVmFeatureList() * * Return a set of strings describing available VM features (this is chiefly * of interest to DDMS). */ static void Dalvik_dalvik_system_VMDebug_getVmFeatureList(const u4* args, JValue* pResult) { std::vector<std::string> features; features.push_back("method-trace-profiling"); features.push_back("method-trace-profiling-streaming"); features.push_back("hprof-heap-dump"); features.push_back("hprof-heap-dump-streaming"); ArrayObject* result = dvmCreateStringArray(features); dvmReleaseTrackedAlloc((Object*) result, dvmThreadSelf()); RETURN_PTR(result); }
/* * 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); }
/* * Find a class by name, initializing it if requested. */ ClassObject* dvmFindClassByName(StringObject* nameObj, Object* loader, bool doInit) { ClassObject* clazz = NULL; char* name = NULL; char* descriptor = NULL; if (nameObj == NULL) { dvmThrowException("Ljava/lang/NullPointerException;", NULL); goto bail; } name = dvmCreateCstrFromString(nameObj); /* * We need to validate and convert the name (from x.y.z to x/y/z). This * is especially handy for array types, since we want to avoid * auto-generating bogus array classes. */ if (!validateClassName(name)) { LOGW("dvmFindClassByName rejecting '%s'\n", name); dvmThrowException("Ljava/lang/ClassNotFoundException;", name); goto bail; } descriptor = dvmDotToDescriptor(name); if (descriptor == NULL) { goto bail; } if (doInit) clazz = dvmFindClass(descriptor, loader); else clazz = dvmFindClassNoInit(descriptor, loader); if (clazz == NULL) { LOGVV("FAIL: load %s (%d)\n", descriptor, doInit); Thread* self = dvmThreadSelf(); Object* oldExcep = dvmGetException(self); dvmAddTrackedAlloc(oldExcep, self); /* don't let this be GCed */ dvmClearException(self); dvmThrowChainedException("Ljava/lang/ClassNotFoundException;", name, oldExcep); dvmReleaseTrackedAlloc(oldExcep, self); } else { LOGVV("GOOD: load %s (%d) --> %p ldr=%p\n", descriptor, doInit, clazz, clazz->classLoader); } bail: free(name); free(descriptor); return clazz; }
/* * Allocate a new instance of the class String, performing first-use * initialization of the class if necessary. Upon success, the * returned value will have all its fields except hashCode already * filled in, including a reference to a newly-allocated char[] for * the contents, sized as given. Additionally, a reference to the * chars array is stored to the pChars pointer. Callers must * subsequently call dvmReleaseTrackedAlloc() on the result pointer. * This function returns NULL on failure. */ static StringObject* makeStringObject(u4 charsLength, ArrayObject** pChars) { /* * The String class should have already gotten found (but not * necessarily initialized) before making it here. We assert it * explicitly, since historically speaking, we have had bugs with * regard to when the class String gets set up. The assert helps * make any regressions easier to diagnose. */ assert(gDvm.classJavaLangString != NULL); if (!dvmIsClassInitialized(gDvm.classJavaLangString)) { /* Perform first-time use initialization of the class. */ if (!dvmInitClass(gDvm.classJavaLangString)) { LOGE("FATAL: Could not initialize class String"); dvmAbort(); } } Object* result = dvmAllocObject(gDvm.classJavaLangString, ALLOC_DEFAULT); if (result == NULL) { return NULL; } ArrayObject* chars = dvmAllocPrimitiveArray('C', charsLength, ALLOC_DEFAULT); if (chars == NULL) { dvmReleaseTrackedAlloc(result, NULL); return NULL; } dvmSetFieldInt(result, STRING_FIELDOFF_COUNT, charsLength); dvmSetFieldObject(result, STRING_FIELDOFF_VALUE, (Object*) chars); dvmReleaseTrackedAlloc((Object*) chars, NULL); /* Leave offset and hashCode set to zero. */ *pChars = chars; return (StringObject*) result; }
/* * static Object[] getSignatureAnnotation() * * Returns the signature annotation. */ static void Dalvik_java_lang_reflect_Method_getSignatureAnnotation( const u4* args, JValue* pResult) { ClassObject* declaringClass = (ClassObject*) args[0]; int slot = args[1]; Method* meth; meth = dvmSlotToMethod(declaringClass, slot); assert(meth != NULL); ArrayObject* arr = dvmGetMethodSignatureAnnotation(meth); dvmReleaseTrackedAlloc((Object*) arr, NULL); RETURN_PTR(arr); }
/* * public Annotation[][] getParameterAnnotations(Class declaringClass, int slot) * * Return the annotations declared for this constructor's parameters. */ static void Dalvik_java_lang_reflect_Constructor_getParameterAnnotations( const u4* args, JValue* pResult) { // ignore thisPtr in args[0] ClassObject* declaringClass = (ClassObject*) args[1]; int slot = args[2]; Method* meth; meth = dvmSlotToMethod(declaringClass, slot); assert(meth != NULL); ArrayObject* annos = dvmGetParameterAnnotations(meth); dvmReleaseTrackedAlloc((Object*)annos, NULL); RETURN_PTR(annos); }
/* * private Object[] getSignatureAnnotation() * * Returns the signature annotation. */ static void Dalvik_java_lang_reflect_Field_getSignatureAnnotation(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] ClassObject* declaringClass = (ClassObject*) args[1]; int slot = args[2]; Field* field; field = dvmSlotToField(declaringClass, slot); assert(field != NULL); ArrayObject* arr = dvmGetFieldSignatureAnnotation(field); dvmReleaseTrackedAlloc((Object*) arr, NULL); RETURN_PTR(arr); }
/* * Resolve a string reference. * * Finding the string is easy. We need to return a reference to a * java/lang/String object, not a bunch of characters, which means the * first time we get here we need to create an interned string. */ StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx) { DvmDex* pDvmDex = referrer->pDvmDex; StringObject* strObj; StringObject* internStrObj; const char* utf8; u4 utf16Size; LOGVV("+++ resolving string, referrer is %s\n", referrer->descriptor); /* * Create a UTF-16 version so we can trivially compare it to what's * already interned. */ utf8 = dexStringAndSizeById(pDvmDex->pDexFile, stringIdx, &utf16Size); strObj = dvmCreateStringFromCstrAndLength(utf8, utf16Size, ALLOC_DEFAULT); if (strObj == NULL) { /* ran out of space in GC heap? */ assert(dvmCheckException(dvmThreadSelf())); goto bail; } /* * Add it to the intern list. The return value is the one in the * intern list, which (due to race conditions) may or may not be * the one we just created. The intern list is synchronized, so * there will be only one "live" version. * * By requesting an immortal interned string, we guarantee that * the returned object will never be collected by the GC. * * A NULL return here indicates some sort of hashing failure. */ internStrObj = dvmLookupImmortalInternedString(strObj); dvmReleaseTrackedAlloc((Object*) strObj, NULL); strObj = internStrObj; if (strObj == NULL) { assert(dvmCheckException(dvmThreadSelf())); goto bail; } /* save a reference so we can go straight to the object next time */ dvmDexSetResolvedString(pDvmDex, stringIdx, strObj); bail: return strObj; }
/* * private static String getBootClassPathResource(String name, int index) * * Find a resource with a matching name in a boot class path entry. * * This mimics the previous VM interface, since we're sharing class libraries. */ static void Dalvik_java_lang_VMClassLoader_getBootClassPathResource( const u4* args, JValue* pResult) { StringObject* nameObj = (StringObject*) args[0]; StringObject* result; int idx = args[1]; char* name; name = dvmCreateCstrFromString(nameObj); if (name == NULL) RETURN_PTR(NULL); result = dvmGetBootPathResource(name, idx); free(name); dvmReleaseTrackedAlloc((Object*)result, NULL); RETURN_PTR(result); }
/* Process all enqueued heap work, including finalizers and reference * enqueueing. Clearing has already been done by the VM. * * Caller must hold gDvm.heapWorkerLock. */ static void doHeapWork(Thread *self) { Object *obj; HeapWorkerOperation op; int numFinalizersCalled, numReferencesEnqueued; assert(gDvm.voffJavaLangObject_finalize >= 0); assert(gDvm.methJavaLangRefReference_enqueueInternal != NULL); numFinalizersCalled = 0; numReferencesEnqueued = 0; while ((obj = dvmGetNextHeapWorkerObject(&op)) != NULL) { Method *method = NULL; /* Make sure the object hasn't been collected since * being scheduled. */ assert(dvmIsValidObject(obj)); /* Call the appropriate method(s). */ if (op == WORKER_FINALIZE) { numFinalizersCalled++; method = obj->clazz->vtable[gDvm.voffJavaLangObject_finalize]; assert(dvmCompareNameDescriptorAndMethod("finalize", "()V", method) == 0); assert(method->clazz != gDvm.classJavaLangObject); callMethod(self, obj, method); } else { assert(op == WORKER_ENQUEUE); assert(dvmGetFieldObject( obj, gDvm.offJavaLangRefReference_queue) != NULL); assert(dvmGetFieldObject( obj, gDvm.offJavaLangRefReference_queueNext) == NULL); numReferencesEnqueued++; callMethod(self, obj, gDvm.methJavaLangRefReference_enqueueInternal); } /* Let the GC collect the object. */ dvmReleaseTrackedAlloc(obj, self); } LOGV("Called %d finalizers\n", numFinalizersCalled); LOGV("Enqueued %d references\n", numReferencesEnqueued); }
/* * private Object getDefaultValue(Class declaringClass, int slot) * * Return the default value for the annotation member represented by * this Method instance. Returns NULL if none is defined. */ static void Dalvik_java_lang_reflect_Method_getDefaultValue(const u4* args, JValue* pResult) { // ignore thisPtr in args[0] ClassObject* declaringClass = (ClassObject*) args[1]; int slot = args[2]; Method* meth; /* make sure this is an annotation class member */ if (!dvmIsAnnotationClass(declaringClass)) RETURN_PTR(NULL); meth = dvmSlotToMethod(declaringClass, slot); assert(meth != NULL); Object* def = dvmGetAnnotationDefaultValue(meth); dvmReleaseTrackedAlloc(def, NULL); RETURN_PTR(def); }
/* * public int constructNative(Object[] args, Class declaringClass, * Class[] parameterTypes, int slot, boolean noAccessCheck) * * We get here through Constructor.newInstance(). The Constructor object * would not be available if the constructor weren't public (per the * definition of Class.getConstructor), so we can skip the method access * check. We can also safely assume the constructor isn't associated * with an interface, array, or primitive class. */ static void Dalvik_java_lang_reflect_Constructor_constructNative( const u4* args, JValue* pResult) { // ignore thisPtr in args[0] ArrayObject* argList = (ArrayObject*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ArrayObject* params = (ArrayObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); Object* newObj; Method* meth; if (dvmIsAbstractClass(declaringClass)) { dvmThrowInstantiationException(declaringClass, NULL); RETURN_VOID(); } /* initialize the class if it hasn't been already */ if (!dvmIsClassInitialized(declaringClass)) { if (!dvmInitClass(declaringClass)) { ALOGW("Class init failed in Constructor.constructNative (%s)", declaringClass->descriptor); assert(dvmCheckException(dvmThreadSelf())); RETURN_VOID(); } } newObj = dvmAllocObject(declaringClass, ALLOC_DEFAULT); if (newObj == NULL) RETURN_PTR(NULL); meth = dvmSlotToMethod(declaringClass, slot); assert(meth != NULL); (void) dvmInvokeMethod(newObj, meth, argList, params, NULL, noAccessCheck); dvmReleaseTrackedAlloc(newObj, NULL); RETURN_PTR(newObj); }
/* * public int constructNative(Object[] args, Class declaringClass, * Class[] parameterTypes, int slot, boolean noAccessCheck) */ static void Dalvik_java_lang_reflect_Constructor_constructNative( const u4* args, JValue* pResult) { // ignore thisPtr in args[0] ArrayObject* argList = (ArrayObject*) args[1]; ClassObject* declaringClass = (ClassObject*) args[2]; ArrayObject* params = (ArrayObject*) args[3]; int slot = args[4]; bool noAccessCheck = (args[5] != 0); Object* newObj; Method* meth; newObj = dvmAllocObject(declaringClass, ALLOC_DEFAULT); if (newObj == NULL) RETURN_PTR(NULL); meth = dvmSlotToMethod(declaringClass, slot); assert(meth != NULL); (void) dvmInvokeMethod(newObj, meth, argList, params, NULL, noAccessCheck); dvmReleaseTrackedAlloc(newObj, NULL); RETURN_PTR(newObj); }