ObjectArray* Java_java_lang_Class_getDeclaredMethods0(Env* env, Class* clazz, jboolean publicOnly) { if (CLASS_IS_PRIMITIVE(clazz) || CLASS_IS_ARRAY(clazz)) return NULL; Method* methods = rvmGetMethods(env, clazz); if (rvmExceptionCheck(env)) return NULL; Method* method; jint length = 0; for (method = methods; method != NULL; method = method->next) { if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) { if (!publicOnly || METHOD_IS_PUBLIC(method)) { length++; } } } ObjectArray* result = NULL; jint i = 0; for (method = methods; method != NULL; method = method->next) { if (!METHOD_IS_CONSTRUCTOR(method) && !METHOD_IS_CLASS_INITIALIZER(method)) { if (!publicOnly || METHOD_IS_PUBLIC(method)) { Object* c = createMethodObject(env, method); if (!c) return NULL; if (!result) { result = rvmNewObjectArray(env, length, c->clazz, NULL, NULL); if (!result) return NULL; } result->values[i++] = c; } } } return result; }
void* lookupInterfaceMethod(Env* env, ClassInfoHeader* header, Object* thiz, char* name, char* desc) { initializeClass(env, header); if (rvmExceptionCheck(env)) return NULL; Class* ownerInterface = header->clazz; if (!rvmIsInstanceOf(env, thiz, ownerInterface)) { char message[256]; snprintf(message, 256, "Class %s does not implement the requested interface %s", rvmToBinaryClassName(env, thiz->clazz->name), rvmToBinaryClassName(env, ownerInterface->name)); rvmThrowIncompatibleClassChangeError(env, message); return NULL; } Method* method = rvmGetInstanceMethod(env, thiz->clazz, name, desc); Object* throwable = rvmExceptionClear(env); if (!method && throwable->clazz != java_lang_NoSuchMethodError) { rvmThrow(env, throwable); return NULL; } if (!method || METHOD_IS_ABSTRACT(method)) { rvmThrowAbstractMethodError(env, ""); // TODO: Message return NULL; } if (!METHOD_IS_PUBLIC(method)) { rvmThrowIllegalAccessError(env, ""); // TODO: Message return NULL; } return method->synchronizedImpl ? method->synchronizedImpl : method->impl; }
static jboolean addProxyMethods(Env* env, Class* proxyClass, Class* clazz, ProxyClassData* proxyClassData) { // Add constructors from the super class and override all overridable methods. Constructors will use // the same impl as the superclass. Overridden methods will have _rvmProxy0 as its impl. if (clazz->superclass) { if (!addProxyMethods(env, proxyClass, clazz->superclass, proxyClassData)) return FALSE; } Method* method = rvmGetMethods(env, clazz); if (rvmExceptionOccurred(env)) return FALSE; for (; method != NULL; method = method->next) { if (!METHOD_IS_STATIC(method) && !METHOD_IS_PRIVATE(method) && !METHOD_IS_FINAL(method) && (!METHOD_IS_CONSTRUCTOR(method) || clazz == proxyClass->superclass)) { void* impl = NULL; jint access = (method->access & (~ACC_ABSTRACT & ~ACC_NATIVE)) | ACC_FINAL; if (METHOD_IS_CONSTRUCTOR(method)) { impl = method->impl; // TODO: For now we make all constructors public to satisfy java.lang.reflect.Proxy. access = ACC_PUBLIC; if (!addProxyMethod(env, proxyClass, method, access, impl)) return FALSE; } else { impl = _proxy0; if (METHOD_IS_PUBLIC(method)) { ProxyMethod* proxyMethod = hasMethod(env, proxyClass, method->name, method->desc); if (rvmExceptionOccurred(env)) return FALSE; if (!proxyMethod) { proxyMethod = addProxyMethod(env, proxyClass, method, access, impl); if (!proxyMethod) return FALSE; } // Record the lookup function in proxyClassData LookupEntry* entry = rvmAllocateMemory(env, sizeof(LookupEntry)); if (!entry) return FALSE; entry->key.name = method->name; entry->key.desc = method->desc; entry->method = proxyMethod; HASH_ADD(hh, proxyClassData->lookupsHash, key, sizeof(LookupKey), entry); } } } } return TRUE; }