| Index: base/android/jni_android.cc
|
| diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc
|
| index 1b7c72c82fa7baa830bb7a8a95896140fb7f0774..2a01063d1ed5c6285e3cef73108f0476b5347384 100644
|
| --- a/base/android/jni_android.cc
|
| +++ b/base/android/jni_android.cc
|
| @@ -6,12 +6,17 @@
|
|
|
| #include <map>
|
|
|
| +#include "base/android/build_info.h"
|
| +#include "base/android/jni_string.h"
|
| #include "base/atomicops.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| #include "base/threading/platform_thread.h"
|
|
|
| namespace {
|
| +using base::android::GetClass;
|
| +using base::android::GetMethodID;
|
| +using base::android::ScopedJavaLocalRef;
|
|
|
| JavaVM* g_jvm = NULL;
|
|
|
| @@ -49,7 +54,48 @@ const base::subtle::AtomicWord kUnlocked = 0;
|
| const base::subtle::AtomicWord kLocked = 1;
|
| base::subtle::AtomicWord g_method_id_map_lock = kUnlocked;
|
|
|
| +std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) {
|
| + ScopedJavaLocalRef<jclass> throwable_clazz =
|
| + GetClass(env, "java/lang/Throwable");
|
| + jmethodID throwable_printstacktrace =
|
| + GetMethodID(env, throwable_clazz, "printStackTrace",
|
| + "(Ljava/io/PrintStream;)V");
|
| +
|
| + // Create an instance of ByteArrayOutputStream.
|
| + ScopedJavaLocalRef<jclass> bytearray_output_stream_clazz =
|
| + GetClass(env, "java/io/ByteArrayOutputStream");
|
| + jmethodID bytearray_output_stream_constructor =
|
| + GetMethodID(env, bytearray_output_stream_clazz, "<init>", "()V");
|
| + jmethodID bytearray_output_stream_tostring =
|
| + GetMethodID(env, bytearray_output_stream_clazz, "toString",
|
| + "()Ljava/lang/String;");
|
| + ScopedJavaLocalRef<jobject> bytearray_output_stream(env,
|
| + env->NewObject(bytearray_output_stream_clazz.obj(),
|
| + bytearray_output_stream_constructor));
|
| +
|
| + // Create an instance of PrintStream.
|
| + ScopedJavaLocalRef<jclass> printstream_clazz =
|
| + GetClass(env, "java/io/PrintStream");
|
| + jmethodID printstream_constructor =
|
| + GetMethodID(env, printstream_clazz, "<init>",
|
| + "(Ljava/io/OutputStream;)V");
|
| + ScopedJavaLocalRef<jobject> printstream(env,
|
| + env->NewObject(printstream_clazz.obj(), printstream_constructor,
|
| + bytearray_output_stream.obj()));
|
| +
|
| + // Call Throwable.printStackTrace(PrintStream)
|
| + env->CallVoidMethod(java_throwable, throwable_printstacktrace,
|
| + printstream.obj());
|
| +
|
| + // Call ByteArrayOutputStream.toString()
|
| + ScopedJavaLocalRef<jstring> exception_string(
|
| + env, static_cast<jstring>(
|
| + env->CallObjectMethod(bytearray_output_stream.obj(),
|
| + bytearray_output_stream_tostring)));
|
| +
|
| + return ConvertJavaStringToUTF8(exception_string);
|
| }
|
| +} // namespace
|
|
|
| namespace base {
|
| namespace android {
|
| @@ -250,15 +296,31 @@ bool HasException(JNIEnv* env) {
|
| bool ClearException(JNIEnv* env) {
|
| if (!HasException(env))
|
| return false;
|
| + env->ExceptionDescribe();
|
| env->ExceptionClear();
|
| return true;
|
| }
|
|
|
| void CheckException(JNIEnv* env) {
|
| - if (HasException(env)) {
|
| - env->ExceptionDescribe();
|
| + if (!HasException(env)) return;
|
| +
|
| + // Ugh, we are going to die, might as well tell breakpad about it.
|
| + jthrowable java_throwable = env->ExceptionOccurred();
|
| + if (!java_throwable) {
|
| + // Nothing we can do.
|
| CHECK(false);
|
| }
|
| +
|
| + // Clear the pending exception, we do have a reference to it.
|
| + env->ExceptionClear();
|
| +
|
| + // Set the exception_string in BuildInfo so that breakpad can read it.
|
| + // RVO should avoid any extra copies of the exception string.
|
| + base::android::BuildInfo::GetInstance()->set_java_exception_info(
|
| + GetJavaExceptionInfo(env, java_throwable));
|
| +
|
| + // Now, feel good about it and die.
|
| + CHECK(false);
|
| }
|
|
|
| } // namespace android
|
|
|