15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/build_info.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_string.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::GetClass;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::MethodID;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ScopedJavaLocalRef;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaVM* g_jvm = NULL;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Leak the global app context, as it is used from a non-joinable worker thread
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that may still be running at shutdown. There is no harm in doing this.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_application_context = LAZY_INSTANCE_INITIALIZER;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jclass> throwable_clazz =
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetClass(env, "java/lang/Throwable");
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID throwable_printstacktrace =
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MethodID::Get<MethodID::TYPE_INSTANCE>(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          env, throwable_clazz.obj(), "printStackTrace",
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "(Ljava/io/PrintStream;)V");
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an instance of ByteArrayOutputStream.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jclass> bytearray_output_stream_clazz =
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetClass(env, "java/io/ByteArrayOutputStream");
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID bytearray_output_stream_constructor =
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MethodID::Get<MethodID::TYPE_INSTANCE>(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          env, bytearray_output_stream_clazz.obj(), "<init>", "()V");
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID bytearray_output_stream_tostring =
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MethodID::Get<MethodID::TYPE_INSTANCE>(
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          env, bytearray_output_stream_clazz.obj(), "toString",
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "()Ljava/lang/String;");
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jobject> bytearray_output_stream(env,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env->NewObject(bytearray_output_stream_clazz.obj(),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bytearray_output_stream_constructor));
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create an instance of PrintStream.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jclass> printstream_clazz =
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetClass(env, "java/io/PrintStream");
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID printstream_constructor =
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MethodID::Get<MethodID::TYPE_INSTANCE>(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          env, printstream_clazz.obj(), "<init>",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "(Ljava/io/OutputStream;)V");
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jobject> printstream(env,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env->NewObject(printstream_clazz.obj(), printstream_constructor,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     bytearray_output_stream.obj()));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call Throwable.printStackTrace(PrintStream)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->CallVoidMethod(java_throwable, throwable_printstacktrace,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printstream.obj());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call ByteArrayOutputStream.toString()
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedJavaLocalRef<jstring> exception_string(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env, static_cast<jstring>(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          env->CallObjectMethod(bytearray_output_stream.obj(),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bytearray_output_stream_tostring)));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ConvertJavaStringToUTF8(exception_string);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace android {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JNIEnv* AttachCurrentThread() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(g_jvm);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JNIEnv* env = NULL;
7931fc3ed1513c41bdd4a09cdd402f3c4f53b0cecdTorne (Richard Coles)  jint ret = g_jvm->AttachCurrentThread(&env, NULL);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(JNI_OK, ret);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return env;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DetachFromVM() {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore the return value, if the thread is not attached, DetachCurrentThread
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will fail. But it is ok as the native thread may never be attached.
8731fc3ed1513c41bdd4a09cdd402f3c4f53b0cecdTorne (Richard Coles)  if (g_jvm)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_jvm->DetachCurrentThread();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitVM(JavaVM* vm) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_jvm);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_jvm = vm;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsVMInitialized() {
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return g_jvm != NULL;
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void InitApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) {
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) {
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // It's safe to set the context more than once if it's the same context.
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(g_application_context.Get().is_null());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_application_context.Get().Reset(context);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const jobject GetApplicationContext() {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!g_application_context.Get().is_null());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_application_context.Get().obj();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jclass clazz = env->FindClass(class_name);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name;
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return ScopedJavaLocalRef<jclass>(env, clazz);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<MethodID::Type type>
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)jmethodID MethodID::Get(JNIEnv* env,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        jclass clazz,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* method_name,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* jni_signature) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID id = type == TYPE_STATIC ?
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env->GetStaticMethodID(clazz, method_name, jni_signature) :
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      env->GetMethodID(clazz, method_name, jni_signature);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(base::android::ClearException(env) || id) <<
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Failed to find " <<
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (type == TYPE_STATIC ? "static " : "") <<
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "method " << method_name << " " << jni_signature;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If |atomic_method_id| set, it'll return immediately. Otherwise, it'll call
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into ::Get() above. If there's a race, it's ok since the values are the same
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (and the duplicated effort will happen only once).
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<MethodID::Type type>
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)jmethodID MethodID::LazyGet(JNIEnv* env,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            jclass clazz,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const char* method_name,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const char* jni_signature,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::subtle::AtomicWord* atomic_method_id) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jmethodID),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 AtomicWord_SmallerThan_jMethodID);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_method_id);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<jmethodID>(value);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jmethodID id = MethodID::Get<type>(env, clazz, method_name, jni_signature);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::subtle::Release_Store(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      atomic_method_id, reinterpret_cast<subtle::AtomicWord>(id));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return id;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Various template instantiations.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template jmethodID MethodID::Get<MethodID::TYPE_STATIC>(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JNIEnv* env, jclass clazz, const char* method_name,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* jni_signature);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template jmethodID MethodID::Get<MethodID::TYPE_INSTANCE>(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JNIEnv* env, jclass clazz, const char* method_name,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* jni_signature);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JNIEnv* env, jclass clazz, const char* method_name,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JNIEnv* env, jclass clazz, const char* method_name,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasException(JNIEnv* env) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return env->ExceptionCheck() != JNI_FALSE;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ClearException(JNIEnv* env) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasException(env))
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->ExceptionDescribe();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->ExceptionClear();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckException(JNIEnv* env) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HasException(env)) return;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exception has been found, might as well tell breakpad about it.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jthrowable java_throwable = env->ExceptionOccurred();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!java_throwable) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do nothing but return false.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(false);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the pending exception, since a local reference is now held.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->ExceptionDescribe();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  env->ExceptionClear();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the exception_string in BuildInfo so that breakpad can read it.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RVO should avoid any extra copies of the exception string.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::android::BuildInfo::GetInstance()->set_java_exception_info(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetJavaExceptionInfo(env, java_throwable));
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, feel good about it and die.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(false);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace android
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
209