Fix JNI ToReflectedMethod for constructor
Returns java.lang.reflect.Constructor object for <init> and <clinit> methods.
Bug: https://code.google.com/p/android/issues/detail?id=72312
Bug: 15885285
Change-Id: I2f4a266b2d9574659673dc6966104860578d709e
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 8842f59..083f179 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -592,7 +592,12 @@
mirror::ArtMethod* m = soa.DecodeMethod(mid);
CHECK(!kMovingMethods);
jobject art_method = soa.AddLocalReference<jobject>(m);
- jobject reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
+ jobject reflect_method;
+ if (m->IsConstructor()) {
+ reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
+ } else {
+ reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
+ }
if (env->ExceptionCheck()) {
return nullptr;
}
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index a933f86..d255ec8 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -380,19 +380,39 @@
TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
+ ASSERT_NE(jlrMethod, nullptr);
+ jclass jlrConstructor = env_->FindClass("java/lang/reflect/Constructor");
+ ASSERT_NE(jlrConstructor, nullptr);
jclass c = env_->FindClass("java/lang/String");
ASSERT_NE(c, nullptr);
- jmethodID mid = env_->GetMethodID(c, "length", "()I");
+
+ jmethodID mid = env_->GetMethodID(c, "<init>", "()V");
ASSERT_NE(mid, nullptr);
- // Turn the mid into a java.lang.reflect.Method...
+ // Turn the mid into a java.lang.reflect.Constructor...
jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
- ASSERT_NE(c, nullptr);
- ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
+ ASSERT_NE(method, nullptr);
+ ASSERT_TRUE(env_->IsInstanceOf(method, jlrConstructor));
// ...and back again.
jmethodID mid2 = env_->FromReflectedMethod(method);
ASSERT_NE(mid2, nullptr);
// Make sure we can actually use it.
- jstring s = env_->NewStringUTF("poop");
+ jstring s = reinterpret_cast<jstring>(env_->AllocObject(c));
+ ASSERT_NE(s, nullptr);
+ env_->CallVoidMethod(s, mid2);
+ ASSERT_EQ(JNI_FALSE, env_->ExceptionCheck());
+
+ mid = env_->GetMethodID(c, "length", "()I");
+ ASSERT_NE(mid, nullptr);
+ // Turn the mid into a java.lang.reflect.Method...
+ method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
+ ASSERT_NE(method, nullptr);
+ ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
+ // ...and back again.
+ mid2 = env_->FromReflectedMethod(method);
+ ASSERT_NE(mid2, nullptr);
+ // Make sure we can actually use it.
+ s = env_->NewStringUTF("poop");
+ ASSERT_NE(s, nullptr);
ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
// Bad arguments.