Fix JNI NoSuchMethodErrors.
No point calling PrettyMethod if you've just determined that your Method* is
NULL...
Also a few other debugging aids.
Change-Id: I8af520716215800b7ffe4aef784b9c4ec15dcb92
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 67acf9d..1963985 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -546,8 +546,9 @@
std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
location_to_dex_cache[location] = dex_cache;
}
- CHECK_EQ(boot_class_path.size() + class_path.size(),
- location_to_dex_cache.size());
+ CHECK(boot_class_path.size() + class_path.size() == location_to_dex_cache.size())
+ << "(" << boot_class_path.size() << " + " << class_path.size()
+ << " != " << location_to_dex_cache.size() << ")";
// reinit boot_class_path with DexFile arguments and found DexCaches
for (size_t i = 0; i != boot_class_path.size(); ++i) {
diff --git a/src/common_test.h b/src/common_test.h
index b56090b..bbf2e2f 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include "heap.h"
#include "runtime.h"
+#include "stl_util.h"
#include "stringprintf.h"
#include "thread.h"
#include "unicode/uclean.h"
@@ -296,14 +297,7 @@
// TODO: isn't gtest supposed to be able to print STL types for itself?
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
- os << "[";
- for (size_t i = 0; i < rhs.size(); ++i) {
- os << rhs[i];
- if (i < rhs.size() - 1) {
- os << ", ";
- }
- }
- os << "]";
+ os << ::art::ToString(rhs);
return os;
}
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index d01d841..144ec22 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -251,6 +251,12 @@
return result;
}
+void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
+ std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
+ ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
+ "no %s method \"%s.%s%s\"", kind, class_descriptor.c_str(), name, sig);
+}
+
jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
@@ -270,12 +276,7 @@
}
if (method == NULL || method->IsStatic() != is_static) {
- std::string method_name(PrettyMethod(method));
- // TODO: try searching for the opposite kind of method from is_static
- // for better diagnostics?
- ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
- "no %s method %s", is_static ? "static" : "non-static",
- method_name.c_str());
+ ThrowNoSuchMethodError(ts, c, name, sig, is_static ? "static" : "non-static");
return NULL;
}
@@ -2097,16 +2098,10 @@
m = c->FindVirtualMethod(name, sig);
}
if (m == NULL) {
- std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
- ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
- "no method \"%s.%s%s\"",
- class_descriptor.c_str(), name, sig);
+ ThrowNoSuchMethodError(ts, c, name, sig, "static or non-static");
return JNI_ERR;
} else if (!m->IsNative()) {
- std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
- ts.Self()->ThrowNewException("Ljava/lang/NoSuchMethodError;",
- "method \"%s.%s%s\" is not native",
- class_descriptor.c_str(), name, sig);
+ ThrowNoSuchMethodError(ts, c, name, sig, "native");
return JNI_ERR;
}
diff --git a/src/object.cc b/src/object.cc
index 0e8e176..f8c9624 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -433,7 +433,7 @@
// Do full linkage and set cache value for next call
result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
}
- CHECK(result != NULL);
+ CHECK(result != NULL) << PrettyMethod(this);
return result;
}
diff --git a/src/stl_util.h b/src/stl_util.h
index 5fcf089..d826510 100644
--- a/src/stl_util.h
+++ b/src/stl_util.h
@@ -3,6 +3,8 @@
#ifndef ART_SRC_STL_UTIL_H_
#define ART_SRC_STL_UTIL_H_
+#include <iostream>
+
namespace art {
// STLDeleteContainerPointers()
@@ -54,6 +56,20 @@
v->clear();
}
+template <class T>
+std::string ToString(const T& v) {
+ std::stringstream os;
+ os << "[";
+ for (size_t i = 0; i < v.size(); ++i) {
+ os << v[i];
+ if (i < v.size() - 1) {
+ os << ", ";
+ }
+ }
+ os << "]";
+ return os.str();
+}
+
} // namespace art
#endif // ART_SRC_STL_UTIL_H_