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 }
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; }
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; } }
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)); }
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); }