return false;
}
- /* and one for the message field, in case we want to show it */
- gDvm.offJavaLangThrowable_message =
- dvmFindFieldOffset(gDvm.classJavaLangThrowable,
- "detailMessage", "Ljava/lang/String;");
- if (gDvm.offJavaLangThrowable_message < 0) {
- LOGE("Unable to find Throwable.detailMessage\n");
- return false;
- }
-
/* and one for the cause field, just 'cause */
gDvm.offJavaLangThrowable_cause =
dvmFindFieldOffset(gDvm.classJavaLangThrowable,
}
/*
+ * Get the message string. We'd like to just grab the field out of
+ * Throwable, but the getMessage() function can be overridden by the
+ * sub-class.
+ *
+ * Returns the message string object, or NULL if it wasn't set or
+ * we encountered a failure trying to retrieve it. The string will
+ * be added to the tracked references table.
+ */
+static StringObject* getExceptionMessage(Object* exception)
+{
+ Thread* self = dvmThreadSelf();
+ Method* getMessageMethod;
+ StringObject* messageStr = NULL;
+
+ assert(exception == self->exception);
+ self->exception = NULL;
+
+ getMessageMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
+ "getMessage", "()Ljava/lang/String;");
+ if (getMessageMethod != NULL) {
+ /* could be in NATIVE mode from CheckJNI, so switch state */
+ ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_RUNNING);
+ JValue result;
+
+ dvmCallMethod(self, getMessageMethod, exception, &result);
+ messageStr = (StringObject*) result.l;
+ dvmAddTrackedAlloc((Object*) messageStr, self);
+
+ dvmChangeStatus(self, oldStatus);
+ } else {
+ LOGW("WARNING: could not find getMessage in %s\n",
+ exception->clazz->descriptor);
+ }
+
+ if (self->exception != NULL) {
+ LOGW("NOTE: exception thrown while retrieving exception message: %s\n",
+ self->exception->clazz->descriptor);
+ }
+
+ self->exception = exception;
+ return messageStr;
+}
+
+/*
* Print the direct stack trace of the given exception to the log.
*/
static void logStackTraceOf(Object* exception)
char* className;
className = dvmDescriptorToDot(exception->clazz->descriptor);
- messageStr = (StringObject*) dvmGetFieldObject(exception,
- gDvm.offJavaLangThrowable_message);
+ messageStr = getExceptionMessage(exception);
if (messageStr != NULL) {
char* cp = dvmCreateCstrFromString(messageStr);
+ dvmReleaseTrackedAlloc((Object*) messageStr, dvmThreadSelf());
+ messageStr = NULL;
+
LOGI("%s: %s\n", className, cp);
free(cp);
} else {
self->threadId, self->status, newStatus);
oldStatus = self->status;
+ if (oldStatus == newStatus)
+ return oldStatus;
if (newStatus == THREAD_RUNNING) {
/*
* the thread is supposed to be suspended. This is possibly faster
* on SMP and slightly more correct, but less convenient.
*/
- assert(oldStatus != THREAD_RUNNING);
android_atomic_acquire_store(newStatus, &self->status);
if (self->suspendCount != 0) {
fullSuspendCheck(self);