Class getField/Method returns NULL if type/args are unresolved.
These changes check that a field's type is resolved before returning it
through getDeclaredField, and that a method's return type and argument
types are resolved before returning it through getDeclaredMethods. This
fixes test failures in libcore MissingClassesTest.
(cherry picked from commit 1ae431a01516b6c91f031aff37c756b7e4f63dd1)
Change-Id: I6bd5601a975e677be6438b1efcb1b1f1ecde900c
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index 5c834f7..6cf7a2c 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -138,9 +138,15 @@
}
std::vector<Field*> fields;
+ FieldHelper fh;
for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
Field* f = c->GetInstanceField(i);
+ fh.ChangeField(f);
if (IsVisibleField(f, publicOnly)) {
+ if (fh.GetType() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
fields.push_back(f);
}
if (env->ExceptionOccurred()) {
@@ -149,7 +155,12 @@
}
for (size_t i = 0; i < c->NumStaticFields(); ++i) {
Field* f = c->GetStaticField(i);
+ fh.ChangeField(f);
if (IsVisibleField(f, publicOnly)) {
+ if (fh.GetType() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
fields.push_back(f);
}
if (env->ExceptionOccurred()) {
@@ -174,15 +185,22 @@
}
static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Class* c = DecodeClass(env, javaClass);
if (c == NULL) {
return NULL;
}
std::vector<Method*> methods;
+ MethodHelper mh;
for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
Method* m = c->GetVirtualMethod(i);
+ mh.ChangeMethod(m);
if (IsVisibleMethod(m, publicOnly)) {
+ if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
methods.push_back(m);
}
if (env->ExceptionOccurred()) {
@@ -191,7 +209,12 @@
}
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
Method* m = c->GetDirectMethod(i);
+ mh.ChangeMethod(m);
if (IsVisibleMethod(m, publicOnly)) {
+ if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
methods.push_back(m);
}
if (env->ExceptionOccurred()) {
@@ -283,6 +306,7 @@
}
static jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass java_class, jobject jname) {
+ ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Class* c = DecodeClass(env, java_class);
if (c == NULL) {
return NULL;
@@ -296,6 +320,10 @@
Field* f = c->GetInstanceField(i);
fh.ChangeField(f);
if (name->Equals(fh.GetName())) {
+ if (fh.GetType() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
return AddLocalReference<jclass>(env, f);
}
}
@@ -303,6 +331,10 @@
Field* f = c->GetStaticField(i);
fh.ChangeField(f);
if (name->Equals(fh.GetName())) {
+ if (fh.GetType() == NULL) {
+ DCHECK(env->ExceptionOccurred());
+ return NULL;
+ }
return AddLocalReference<jclass>(env, f);
}
}
diff --git a/src/object_utils.h b/src/object_utils.h
index cbad7b0..631425e 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -456,6 +456,10 @@
ObjectArray<Class>* result = ObjectArray<Class>::Alloc(array_class, num_params);
for (uint32_t i = 0; i < num_params; i++) {
Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_);
+ if (param_type == NULL) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return NULL;
+ }
result->Set(i, param_type);
}
return result;
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index e76e89f..93d4728 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1164,7 +1164,10 @@
// reset index, will index into param type array which doesn't include the receiver
param_index = 0;
ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
- DCHECK(param_types != NULL);
+ if (param_types == NULL) {
+ CHECK(self->IsExceptionPending());
+ return;
+ }
// Check number of parameter types agrees with number from the Method - less 1 for the receiver.
DCHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1);
while (cur_arg < args_in_regs && param_index < (num_params - 1)) {