/* * Returns a human-readable summary of an exception object. The buffer will * be populated with the "binary" class name and, if present, the * exception message. */ static bool getExceptionSummary(C_JNIEnv* env, jthrowable exception, std::string& result) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); /* get the name of the exception's class */ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail scoped_local_ref<jclass> classClass(env, (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail jmethodID classGetNameMethod = (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;"); scoped_local_ref<jstring> classNameStr(env, (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod)); if (classNameStr.get() == NULL) { (*env)->ExceptionClear(e); result = "<error getting class name>"; return false; } const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL); if (classNameChars == NULL) { (*env)->ExceptionClear(e); result = "<error getting class name UTF-8>"; return false; } result += classNameChars; (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars); /* if the exception has a detail message, get that */ jmethodID getMessage = (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;"); scoped_local_ref<jstring> messageStr(env, (jstring) (*env)->CallObjectMethod(e, exception, getMessage)); if (messageStr.get() == NULL) { return true; } result += ": "; const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (messageChars != NULL) { result += messageChars; (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars); } else { result += "<error getting message>"; (*env)->ExceptionClear(e); // clear OOM } return true; }
/* * Returns a human-readable summary of an exception object. The buffer will * be populated with the "binary" class name and, if present, the * exception message. */ static char* getExceptionSummary0(C_JNIEnv* env, jthrowable exception) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); /* get the name of the exception's class */ scoped_local_ref<jclass> exceptionClass(env, (*env)->GetObjectClass(e, exception)); // can't fail scoped_local_ref<jclass> classClass(env, (*env)->GetObjectClass(e, exceptionClass.get())); // java.lang.Class, can't fail jmethodID classGetNameMethod = (*env)->GetMethodID(e, classClass.get(), "getName", "()Ljava/lang/String;"); scoped_local_ref<jstring> classNameStr(env, (jstring) (*env)->CallObjectMethod(e, exceptionClass.get(), classGetNameMethod)); if (classNameStr.get() == NULL) { return NULL; } /* get printable string */ const char* classNameChars = (*env)->GetStringUTFChars(e, classNameStr.get(), NULL); if (classNameChars == NULL) { return NULL; } /* if the exception has a detail message, get that */ jmethodID getMessage = (*env)->GetMethodID(e, exceptionClass.get(), "getMessage", "()Ljava/lang/String;"); scoped_local_ref<jstring> messageStr(env, (jstring) (*env)->CallObjectMethod(e, exception, getMessage)); if (messageStr.get() == NULL) { return strdup(classNameChars); } char* result = NULL; const char* messageChars = (*env)->GetStringUTFChars(e, messageStr.get(), NULL); if (messageChars != NULL) { asprintf(&result, "%s: %s", classNameChars, messageChars); (*env)->ReleaseStringUTFChars(e, messageStr.get(), messageChars); } else { (*env)->ExceptionClear(e); // clear OOM asprintf(&result, "%s: <error getting message>", classNameChars); } (*env)->ReleaseStringUTFChars(e, classNameStr.get(), classNameChars); return result; }