summaryrefslogtreecommitdiffstats
path: root/src/reflection.cc
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2011-09-23 19:30:41 -0700
committerElliott Hughes <enh@google.com>2011-09-25 10:29:48 -0700
commit2a20cfd0b7fc81099f5de0da782ebcc1cb262792 (patch)
treeef9b496f2ea83edce5cbe4a427dbaafd710bff16 /src/reflection.cc
parent65ca077378935beb113bb5aec5e890054ca3286e (diff)
downloadart-2a20cfd0b7fc81099f5de0da782ebcc1cb262792.zip
art-2a20cfd0b7fc81099f5de0da782ebcc1cb262792.tar.gz
art-2a20cfd0b7fc81099f5de0da782ebcc1cb262792.tar.bz2
Implement java.lang.reflect.Constructor.constructNative.
Change-Id: Iefa92ad1bd89073d4bfa9a80b9e4f0dea90a5849
Diffstat (limited to 'src/reflection.cc')
-rw-r--r--src/reflection.cc69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/reflection.cc b/src/reflection.cc
index 3edb9f7..c560053 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -48,6 +48,75 @@ void InitBoxingMethods(JNIEnv* env) {
InitBoxingMethod(env, gShort_valueOf, JniConstants::shortClass, "(S)Ljava/lang/Short;");
}
+jobject InvokeMethod(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs, jobject javaParams) {
+ Thread* self = Thread::Current();
+ ScopedThreadStateChange tsc(self, Thread::kRunnable);
+
+ jmethodID mid = env->FromReflectedMethod(javaMethod);
+ Method* m = reinterpret_cast<Method*>(mid);
+
+ Class* declaring_class = m->GetDeclaringClass();
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true)) {
+ return NULL;
+ }
+
+ Object* receiver = NULL;
+ if (!m->IsStatic()) {
+ // Check that the receiver is non-null and an instance of the field's declaring class.
+ receiver = Decode<Object*>(env, javaReceiver);
+ if (!VerifyObjectInClass(env, receiver, declaring_class)) {
+ return NULL;
+ }
+
+ // Find the actual implementation of the virtual method.
+ m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m);
+ }
+
+ // Get our arrays of arguments and their types, and check they're the same size.
+ ObjectArray<Object>* objects = Decode<ObjectArray<Object>*>(env, javaArgs);
+ ObjectArray<Class>* classes = Decode<ObjectArray<Class>*>(env, javaParams);
+ int32_t arg_count = (objects != NULL) ? objects->GetLength() : 0;
+ if (arg_count != classes->GetLength()) {
+ self->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+ "wrong number of arguments; expected %d, got %d",
+ classes->GetLength(), arg_count);
+ return NULL;
+ }
+
+ // Translate javaArgs to a jvalue[].
+ UniquePtr<jvalue[]> args(new jvalue[arg_count]);
+ JValue* decoded_args = reinterpret_cast<JValue*>(args.get());
+ for (int32_t i = 0; i < arg_count; ++i) {
+ Object* arg = objects->Get(i);
+ Class* dst_class = classes->Get(i);
+ if (dst_class->IsPrimitive()) {
+ if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
+ return NULL;
+ }
+ } else {
+ args[i].l = AddLocalReference<jobject>(env, arg);
+ }
+ }
+
+ // Invoke the method.
+ JValue value = InvokeWithJValues(env, javaReceiver, mid, args.get());
+
+ // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
+ if (self->IsExceptionPending()) {
+ jthrowable th = env->ExceptionOccurred();
+ env->ExceptionClear();
+ jclass exception_class = env->FindClass("java/lang/reflect/InvocationTargetException");
+ jmethodID mid = env->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
+ jobject exception_instance = env->NewObject(exception_class, mid, th);
+ env->Throw(reinterpret_cast<jthrowable>(exception_instance));
+ return NULL;
+ }
+
+ // Box if necessary and return.
+ BoxPrimitive(env, m->GetReturnType(), value);
+ return AddLocalReference<jobject>(env, value.l);
+}
+
bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
if (o == NULL) {
jniThrowNullPointerException(env, "receiver for non-static field access was null");