Esempio n. 1
0
static jboolean getAnnotationDefaultIterator(Env* env, jbyte type, void* attributes, void* data) {
    Object** result = (Object**) ((void**) data)[0];
    Method* method = (Method*) ((void**) data)[1];
    if (type == ANNOTATION_DEFAULT) {
        Class* c = findType(env, rvmGetReturnType(method->desc), method->clazz->classLoader);
        if (c) {
            jvalue value = {0};
            if (parseElementValue(env, &attributes, c, method->clazz->classLoader, &value)) {
                *result = rvmBox(env, c, &value);
            }
        }
        return FALSE; // Stop iterating
    }
    return TRUE; // Continue with next attribute
}
Esempio n. 2
0
static jboolean getAnnotationValue(Env* env, void** attributes, Class* expectedAnnotationClass, Object* classLoader,
        jvalue* result, jboolean ignoreClassNotFound) {

    char* annotationTypeName = getString(attributes);
    if (expectedAnnotationClass && strncmp(&annotationTypeName[1], expectedAnnotationClass->name, strlen(expectedAnnotationClass->name))) {
        return throwFormatError(env, rvmFromBinaryClassName(env, expectedAnnotationClass->name));
    }

    Class* annotationClass = expectedAnnotationClass;
    if (!annotationClass) {
        annotationClass = rvmFindClassByDescriptor(env, annotationTypeName, classLoader);
        if (!annotationClass) {
            if (ignoreClassNotFound && rvmExceptionOccurred(env)->clazz == java_lang_ClassNotFoundException) {
                rvmExceptionClear(env);
                jint length = getInt(attributes);
                for (jint i = 0; i < length; i++) {
                    getString(attributes);
                    skipElementValue(attributes);
                }
            }
            return FALSE;
        }
    }

    // Find the annotation impl class
    Class* annotationImplClass = findAnnotationImplClass(env, annotationClass, classLoader);
    if (rvmExceptionCheck(env)) return FALSE;

    jint length = getInt(attributes);
    if (length == 0) {
        // No member values specified. Use a singleton instance.
        Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$createSingleton", "()Ljava/lang/Object;");
        if (rvmExceptionCheck(env)) return FALSE;
        Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod);
        if (rvmExceptionCheck(env)) return FALSE;
        result->l = (jobject) annotationObject;
        return TRUE;
    }

    // Call the annotation impl $create() method
    Method* factoryMethod = rvmGetClassMethod(env, annotationImplClass, "$create", "()Ljava/lang/Object;");
    if (rvmExceptionCheck(env)) return FALSE;
    Object* annotationObject = rvmCallObjectClassMethod(env, annotationImplClass, factoryMethod);
    if (rvmExceptionCheck(env)) return FALSE;

    jint i = 0;
    for (i = 0; i < length; i++) {
        char* name = getString(attributes);
        Method* method = getAnnotationValueMethod(env, annotationClass, name);
        if (rvmExceptionCheck(env)) return FALSE;
        if (!method) {
            skipElementValue(attributes);
        } else {
            const char* memberDesc = rvmGetReturnType(method->desc);
            Class* type = findType(env, memberDesc, method->clazz->classLoader);
            Object* value = NULL;
            if (!type) {
                value = rvmExceptionClear(env);
            } else {
                jvalue v = {0};
                if (!parseElementValue(env, attributes, type, classLoader, &v)) {
                    value = rvmExceptionClear(env);
                } else {
                    value = rvmBox(env, type, &v);
                }
            }

            InstanceField* field = getAnnotationMemberField(env, annotationImplClass, method->name);
            if (!field) return FALSE;

            rvmSetObjectInstanceFieldValue(env, annotationObject, field, value);
            if (rvmExceptionCheck(env)) return FALSE;
        }
    }

    result->l = (jobject) annotationObject;
    return TRUE;
}
Esempio n. 3
0
Object* Java_java_lang_reflect_Method_internalInvoke(Env* env, Class* clazz, jlong methodPtr, ObjectArray* parameterTypes, Object* receiver, ObjectArray* args) {
    Method* method = (Method*) LONG_TO_PTR(methodPtr);

    /*
     * The Java code has already checked that the method is accessible
     * to the the caller, that the receiver isn't null (for non static methods),
     * that the receiver is an instance of the declaring class (for non static methods)
     * and that the number of arguments are correct. The args array is never null.
     */

    jvalue* jvalueArgs = validateAndUnwrapArgs(env, parameterTypes, args);
    if (!jvalueArgs) return NULL;

    const char* retDesc = rvmGetReturnType(method->desc);

    jvalue jvalueRet[1];
    if (METHOD_IS_STATIC(method)) {
        switch (retDesc[0]) {
        case 'V':
            rvmCallVoidClassMethodA(env, method->clazz, method, jvalueArgs);
            jvalueRet->l = NULL;
            break;
        case 'Z':
            jvalueRet->z = rvmCallBooleanClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'B':
            jvalueRet->b = rvmCallByteClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'S':
            jvalueRet->s = rvmCallShortClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'C':
            jvalueRet->c = rvmCallCharClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'I':
            jvalueRet->i = rvmCallIntClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'J':
            jvalueRet->j = rvmCallLongClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'F':
            jvalueRet->f = rvmCallFloatClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        case 'D':
            jvalueRet->d = rvmCallDoubleClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        default:
            jvalueRet->l = (jobject) rvmCallObjectClassMethodA(env, method->clazz, method, jvalueArgs);
            break;
        }
    } else {
        switch (retDesc[0]) {
        case 'V':
            rvmCallVoidInstanceMethodA(env, receiver, method, jvalueArgs);
            jvalueRet->l = NULL;
            break;
        case 'Z':
            jvalueRet->z = rvmCallBooleanInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'B':
            jvalueRet->b = rvmCallByteInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'S':
            jvalueRet->s = rvmCallShortInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'C':
            jvalueRet->c = rvmCallCharInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'I':
            jvalueRet->i = rvmCallIntInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'J':
            jvalueRet->j = rvmCallLongInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'F':
            jvalueRet->f = rvmCallFloatInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        case 'D':
            jvalueRet->d = rvmCallDoubleInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        default:
            jvalueRet->l = (jobject) rvmCallObjectInstanceMethodA(env, receiver, method, jvalueArgs);
            break;
        }
    }

    if (rvmExceptionCheck(env)) {
        throwInvocationTargetException(env, rvmExceptionOccurred(env));
        return NULL;
    }

    if (retDesc[0] != 'L' && retDesc[0] != '[') {
        // Return type is primitive. Box it.
        Class* retType = rvmFindClassByDescriptor(env, retDesc, NULL);
        return rvmBox(env, retType, jvalueRet);
    } else {
        return (Object*) jvalueRet->l;
    }
}
Esempio n. 4
0
void _rvmProxyHandler(CallInfo* callInfo) {
    Env* env = (Env*) proxy0NextPtr(callInfo);
    Object* receiver = (Object*) proxy0NextPtr(callInfo);
    Class* proxyClass = receiver->clazz;
    ProxyClassData* proxyClassData = (ProxyClassData*) proxyClass->data;

    LookupKey key;
    memset(&key, 0, sizeof(LookupKey));
    key.name = (char*) env->reserved0;
    key.desc = (char*) env->reserved1;
    LookupEntry* entry;
    HASH_FIND(hh, proxyClassData->lookupsHash, &key, sizeof(LookupKey), entry);
    if (!entry) {
        rvmThrowNoSuchMethodError(env, "Failed to determine which method was called on proxy class");
        goto error;
    }

    ProxyMethod* method = entry->method;

    rvmPushGatewayFrameProxy(env, method);

    jint argsCount = rvmGetParameterCount((Method*) method);
    jvalue *jvalueArgs = NULL;
    if (argsCount > 0) {
        jvalueArgs = (jvalue*) rvmAllocateMemory(env, sizeof(jvalue) * argsCount);
        if (!jvalueArgs) goto errorPop;

        const char* desc = method->method.desc;
        const char* c;
        jint i = 0;
        while ((c = rvmGetNextParameterType(&desc))) {
            switch (c[0]) {
            case 'B':
                jvalueArgs[i++].b = (jbyte) proxy0NextInt(callInfo);
                break;
            case 'Z':
                jvalueArgs[i++].z = (jboolean) proxy0NextInt(callInfo);
                break;
            case 'S':
                jvalueArgs[i++].s = (jshort) proxy0NextInt(callInfo);
                break;
            case 'C':
                jvalueArgs[i++].c = (jchar) proxy0NextInt(callInfo);
                break;
            case 'I':
                jvalueArgs[i++].i = proxy0NextInt(callInfo);
                break;
            case 'J':
                jvalueArgs[i++].j = proxy0NextLong(callInfo);
                break;
            case 'F':
                jvalueArgs[i++].f = proxy0NextFloat(callInfo);
                break;
            case 'D':
                jvalueArgs[i++].d = proxy0NextDouble(callInfo);
                break;
            case '[':
            case 'L':
                jvalueArgs[i++].l = (jobject) proxy0NextPtr(callInfo);
                break;
            }
        }
    }

    jvalue returnValue;
    proxyClassData->handler(env, receiver, method, jvalueArgs, &returnValue);

    rvmPopGatewayFrame(env);

    if (rvmExceptionCheck(env)) goto error;

    proxy0ReturnInt(callInfo, 0);
    switch (rvmGetReturnType(method->method.desc)[0]) {
    case 'B':
        proxy0ReturnInt(callInfo, (jint) returnValue.b);
        break;
    case 'Z':
        proxy0ReturnInt(callInfo, (jint) returnValue.z);
        break;
    case 'S':
        proxy0ReturnInt(callInfo, (jint) returnValue.s);
        break;
    case 'C':
        proxy0ReturnInt(callInfo, (jint) returnValue.c);
        break;
    case 'I':
        proxy0ReturnInt(callInfo, returnValue.i);
        break;
    case 'J':
        proxy0ReturnLong(callInfo, returnValue.j);
        break;
    case 'F':
        proxy0ReturnFloat(callInfo, returnValue.f);
        break;
    case 'D':
        proxy0ReturnDouble(callInfo, returnValue.d);
        break;
    case '[':
    case 'L':
        proxy0ReturnPtr(callInfo, returnValue.l);
        break;
    }

    return;

errorPop:
    rvmPopGatewayFrame(env);
error:
    rvmRaiseException(env, rvmExceptionOccurred(env));
}
Esempio n. 5
0
Class* Java_java_lang_reflect_Method_getReturnType(Env* env, Class* clazz, jlong methodPtr) {
    Method* method = (Method*) LONG_TO_PTR(methodPtr);
    return rvmFindClassByDescriptor(env, rvmGetReturnType(method->desc), method->clazz->classLoader);
}