Esempio n. 1
0
/*
 * "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;
}
Esempio n. 2
0
/*
 * 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;
}
Esempio n. 3
0
/*
 * 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;
}