Even better reflection IllegalArgumentException detail messages and less code.
Also ensure that the new 200-reflection-errors run-test test gets run
by the "test-art" make target.
Bug: 6504175
Change-Id: I5afee8845715151d25ed4751381b6ceb8cb4eca5
diff --git a/Android.mk b/Android.mk
index 6eb4299..aa567a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -123,7 +123,7 @@
TEST_ART_HOST_RUN_TEST_TARGETS += test-art-host-run-test-$(1)
endef
-$(foreach test, $(wildcard art/test/0*), $(eval $(call declare-test-art-host-run-test,$(notdir $(test)))))
+$(foreach test, $(wildcard art/test/[0-9]*), $(eval $(call declare-test-art-host-run-test,$(notdir $(test)))))
.PHONY: test-art-host-run-test
test-art-host-run-test: $(TEST_ART_HOST_RUN_TEST_TARGETS)
@@ -162,7 +162,7 @@
TEST_ART_TARGET_RUN_TEST_TARGETS += test-art-target-run-test-$(1)
endef
-$(foreach test, $(wildcard art/test/0*), $(eval $(call declare-test-art-target-run-test,$(notdir $(test)))))
+$(foreach test, $(wildcard art/test/[0-9]*), $(eval $(call declare-test-art-target-run-test,$(notdir $(test)))))
.PHONY: test-art-target-run-test
test-art-target-run-test: $(TEST_ART_TARGET_RUN_TEST_TARGETS)
diff --git a/src/reflection.cc b/src/reflection.cc
index 6763100..12ecbe1 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -90,18 +90,13 @@
for (uint32_t i = 0; i < arg_count; ++i) {
Object* arg = objects->Get(i);
Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_);
- if (dst_class->IsPrimitive()) {
- if (!UnboxPrimitiveForArgument(arg, dst_class, decoded_args[i], i)) {
+ if (dst_class->IsPrimitive() || (arg != NULL && !arg->InstanceOf(dst_class))) {
+ // We want to actually unbox primitives, but only reuse the error reporting for reference types.
+ if (!UnboxPrimitiveForArgument(arg, dst_class, decoded_args[i], m, i)) {
return NULL;
}
- } else if (arg != NULL && !arg->InstanceOf(dst_class)) {
- self->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
- "argument %d has type %s, got %s",
- i + 1,
- PrettyDescriptor(dst_class).c_str(),
- PrettyTypeOf(arg).c_str());
- return NULL;
} else {
+ // We already tested that these types are compatible.
args[i].l = AddLocalReference<jobject>(env, arg);
}
}
@@ -271,9 +266,10 @@
m->Invoke(self, NULL, args, &value);
}
-static std::string UnboxingFailureKind(int index, Field* f) {
- if (index != -1) {
- return StringPrintf("argument %d", index + 1); // Humans count from 1.
+static std::string UnboxingFailureKind(Method* m, int index, Field* f) {
+ if (m != NULL && index != -1) {
+ ++index; // Humans count from 1.
+ return StringPrintf("method %s argument %d", PrettyMethod(m, false).c_str(), index);
}
if (f != NULL) {
return "field " + PrettyField(f, false);
@@ -281,12 +277,12 @@
return "result";
}
-static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, int index, Field* f) {
+static bool UnboxPrimitive(Object* o, Class* dst_class, JValue& unboxed_value, Method* m, int index, Field* f) {
if (!dst_class->IsPrimitive()) {
if (o != NULL && !o->InstanceOf(dst_class)) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"%s has type %s, got %s",
- UnboxingFailureKind(index, f).c_str(),
+ UnboxingFailureKind(m, index, f).c_str(),
PrettyDescriptor(dst_class).c_str(),
PrettyTypeOf(o).c_str());
return false;
@@ -296,14 +292,14 @@
} else if (dst_class->GetPrimitiveType() == Primitive::kPrimVoid) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"can't unbox %s to void",
- UnboxingFailureKind(index, f).c_str());
+ UnboxingFailureKind(m, index, f).c_str());
return false;
}
if (o == NULL) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"%s has type %s, got null",
- UnboxingFailureKind(index, f).c_str(),
+ UnboxingFailureKind(m, index, f).c_str(),
PrettyDescriptor(dst_class).c_str());
return false;
}
@@ -340,7 +336,7 @@
} else {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
"%s has type %s, got %s",
- UnboxingFailureKind(index, f).c_str(),
+ UnboxingFailureKind(m, index, f).c_str(),
PrettyDescriptor(dst_class).c_str(),
PrettyDescriptor(src_descriptor.c_str()).c_str());
return false;
@@ -350,17 +346,18 @@
boxed_value, unboxed_value);
}
-bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, size_t index) {
- return UnboxPrimitive(o, dst_class, unboxed_value, index, NULL);
+bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, Method* m, size_t index) {
+ CHECK(m != NULL);
+ return UnboxPrimitive(o, dst_class, unboxed_value, m, index, NULL);
}
bool UnboxPrimitiveForField(Object* o, Class* dst_class, JValue& unboxed_value, Field* f) {
CHECK(f != NULL);
- return UnboxPrimitive(o, dst_class, unboxed_value, -1, f);
+ return UnboxPrimitive(o, dst_class, unboxed_value, NULL, -1, f);
}
bool UnboxPrimitiveForResult(Object* o, Class* dst_class, JValue& unboxed_value) {
- return UnboxPrimitive(o, dst_class, unboxed_value, -1, NULL);
+ return UnboxPrimitive(o, dst_class, unboxed_value, NULL, -1, NULL);
}
} // namespace art
diff --git a/src/reflection.h b/src/reflection.h
index aabf513..50c36d7 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -25,11 +25,12 @@
class Class;
class Field;
union JValue;
+class Method;
class Object;
void InitBoxingMethods();
void BoxPrimitive(Primitive::Type src_class, JValue& value);
-bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, size_t index);
+bool UnboxPrimitiveForArgument(Object* o, Class* dst_class, JValue& unboxed_value, Method* m, size_t index);
bool UnboxPrimitiveForField(Object* o, Class* dst_class, JValue& unboxed_value, Field* f);
bool UnboxPrimitiveForResult(Object* o, Class* dst_class, JValue& unboxed_value);
diff --git a/test/200-reflection-errors/expected.txt b/test/200-reflection-errors/expected.txt
index b5b201d..d042d05 100644
--- a/test/200-reflection-errors/expected.txt
+++ b/test/200-reflection-errors/expected.txt
@@ -1,5 +1,5 @@
field A.b has type java.lang.String, got java.lang.Integer
field A.i has type int, got null
field A.i has type int, got java.lang.String
-argument 2 has type java.lang.String, got java.lang.Integer
-argument 1 has type int, got null
+method A.m argument 2 has type java.lang.String, got java.lang.Integer
+method A.m argument 1 has type int, got null