/* * "Reallocate" a piece of memory. * * If the new size is <= the old size, we return the original pointer * without doing anything. * * If the new size is > the old size, we allocate new storage, copy the * old stuff over, and mark the new stuff as free. */ void* dvmLinearRealloc(Object* classLoader, void* mem, size_t newSize) { #ifdef DISABLE_LINEAR_ALLOC return realloc(mem, newSize); #endif LinearAllocHdr* pHdr = getHeader(classLoader); /* make sure we have the right region (and mem != NULL) */ assert(mem != NULL); assert(mem >= (void*) pHdr->mapAddr && mem < (void*) (pHdr->mapAddr + pHdr->curOffset)); const u4* pLen = getBlockHeader(mem); LOGV("--- LinearRealloc(%d) old=%d\n", newSize, *pLen); /* handle size reduction case */ if (*pLen >= newSize) { if (ENFORCE_READ_ONLY) dvmLinearSetReadWrite(classLoader, mem); return mem; } void* newMem; newMem = dvmLinearAlloc(classLoader, newSize); assert(newMem != NULL); memcpy(newMem, mem, *pLen); dvmLinearFree(classLoader, mem); return newMem; }
/* * Helper function, replaces strdup(). */ char *dvmLinearStrdup(Object *classLoader, const char *str) { #ifdef DISABLE_LINEAR_ALLOC return strdup(str); #endif int len = strlen(str); void *mem = dvmLinearAlloc(classLoader, len + 1); memcpy(mem, str, len + 1); if (ENFORCE_READ_ONLY) dvmLinearSetReadOnly(classLoader, mem); return (char *) mem; }
/* * Generate a proxy class with the specified name, interfaces, and loader. * "interfaces" is an array of class objects. * * The interpreted code has done all of the necessary checks, e.g. we know * that "interfaces" contains only interface classes. * * On failure we leave a partially-created class object sitting around, * but the garbage collector will take care of it. */ ClassObject* dvmGenerateProxyClass(StringObject* str, ArrayObject* interfaces, Object* loader) { int result = -1; char* nameStr = NULL; Method** methods = NULL; ClassObject* newClass = NULL; int i; nameStr = dvmCreateCstrFromString(str); if (nameStr == NULL) { dvmThrowException("Ljava/lang/IllegalArgumentException;", "missing name"); goto bail; } LOGV("+++ Generate proxy class '%s' %p from %d interface classes\n", nameStr, loader, interfaces->length); /* * Characteristics of a Proxy class: * - concrete class, public and final * - superclass is java.lang.reflect.Proxy * - implements all listed interfaces (req'd for instanceof) * - has one method for each method in the interfaces (barring duplicates) * - has one constructor (takes an InvocationHandler arg) * - has overrides for hashCode, equals, and toString (these come first) * - has one field, a reference to the InvocationHandler object * * The idea here is to create a class object and fill in the details * as we would in loadClassFromDex(), and then call dvmLinkClass() to do * all the heavy lifting (notably populating the virtual and interface * method tables). */ /* * Generate a temporary list of virtual methods. */ int methodCount; if (!gatherMethods(interfaces, &methods, &methodCount)) goto bail; /* * Allocate storage for the class object and set some basic fields. */ newClass = (ClassObject*) dvmMalloc(sizeof(*newClass), ALLOC_DEFAULT); if (newClass == NULL) return NULL; DVM_OBJECT_INIT(&newClass->obj, gDvm.unlinkedJavaLangClass); newClass->descriptorAlloc = dvmNameToDescriptor(nameStr); newClass->descriptor = newClass->descriptorAlloc; newClass->accessFlags = ACC_PUBLIC | ACC_FINAL; newClass->super = gDvm.classJavaLangReflectProxy; newClass->primitiveType = PRIM_NOT; newClass->classLoader = loader; #if WITH_HPROF && WITH_HPROF_STACK newClass->hprofSerialNumber = 0; hprofFillInStackTrace(newClass); #endif /* * Add direct method definitions. We have one (the constructor). */ newClass->directMethodCount = 1; newClass->directMethods = (Method*) dvmLinearAlloc(newClass->classLoader, 1 * sizeof(Method)); createConstructor(newClass, &newClass->directMethods[0]); dvmLinearReadOnly(newClass->classLoader, newClass->directMethods); /* * Add virtual method definitions. */ newClass->virtualMethodCount = methodCount; newClass->virtualMethods = (Method*) dvmLinearAlloc(newClass->classLoader, newClass->virtualMethodCount * sizeof(Method)); for (i = 0; i < newClass->virtualMethodCount; i++) { createHandlerMethod(newClass, &newClass->virtualMethods[i],methods[i]); } dvmLinearReadOnly(newClass->classLoader, newClass->virtualMethods); /* * Add interface list. */ int interfaceCount = interfaces->length; ClassObject** ifArray = (ClassObject**) interfaces->contents; newClass->interfaceCount = interfaceCount; newClass->interfaces = (ClassObject**)dvmLinearAlloc(newClass->classLoader, sizeof(ClassObject*) * interfaceCount); for (i = 0; i < interfaceCount; i++) newClass->interfaces[i] = ifArray[i]; dvmLinearReadOnly(newClass->classLoader, newClass->interfaces); /* * The class has one instance field, "protected InvocationHandler h", * which is filled in by the constructor. */ newClass->ifieldCount = 1; newClass->ifields = (InstField*) dvmLinearAlloc(newClass->classLoader, 1 * sizeof(InstField)); InstField* ifield = &newClass->ifields[0]; ifield->field.clazz = newClass; ifield->field.name = "h"; ifield->field.signature = "Ljava/lang/reflect/InvocationHandler;"; ifield->field.accessFlags = ACC_PROTECTED; ifield->byteOffset = -1; /* set later */ dvmLinearReadOnly(newClass->classLoader, newClass->ifields); /* * Everything is ready. See if the linker will lap it up. */ newClass->status = CLASS_LOADED; if (!dvmLinkClass(newClass, true)) { LOGI("Proxy class link failed\n"); goto bail; } /* * All good. Add it to the hash table. We should NOT see a collision * here; if we do, it means the caller has screwed up and provided us * with a duplicate name. */ if (!dvmAddClassToHash(newClass)) { LOGE("ERROR: attempted to generate %s more than once\n", newClass->descriptor); goto bail; } result = 0; bail: free(nameStr); free(methods); if (result != 0) { /* must free innards explicitly if we didn't finish linking */ dvmFreeClassInnards(newClass); newClass = NULL; dvmThrowException("Ljava/lang/RuntimeException;", NULL); } /* this allows the GC to free it */ dvmReleaseTrackedAlloc((Object*) newClass, NULL); return newClass; }