Beispiel #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
}
Beispiel #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;
}
Beispiel #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;
    }
}