OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/android/jni_android.h" | 5 #include "base/android/jni_android.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
11 #include "base/android/jni_utils.h" | |
11 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 | 14 |
14 namespace { | 15 namespace { |
15 using base::android::GetClass; | 16 using base::android::GetClass; |
16 using base::android::MethodID; | 17 using base::android::MethodID; |
17 using base::android::ScopedJavaLocalRef; | 18 using base::android::ScopedJavaLocalRef; |
18 | 19 |
19 JavaVM* g_jvm = NULL; | 20 JavaVM* g_jvm = NULL; |
20 // Leak the global app context, as it is used from a non-joinable worker thread | 21 // Leak the global app context, as it is used from a non-joinable worker thread |
21 // that may still be running at shutdown. There is no harm in doing this. | 22 // that may still be running at shutdown. There is no harm in doing this. |
22 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky | 23 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky |
23 g_application_context = LAZY_INSTANCE_INITIALIZER; | 24 g_application_context = LAZY_INSTANCE_INITIALIZER; |
25 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky | |
26 g_class_loader = LAZY_INSTANCE_INITIALIZER; | |
27 jmethodID g_class_loader_load_class_method_id = 0; | |
24 | 28 |
25 std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) { | 29 std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) { |
26 ScopedJavaLocalRef<jclass> throwable_clazz = | 30 ScopedJavaLocalRef<jclass> throwable_clazz = |
27 GetClass(env, "java/lang/Throwable"); | 31 GetClass(env, "java/lang/Throwable"); |
28 jmethodID throwable_printstacktrace = | 32 jmethodID throwable_printstacktrace = |
29 MethodID::Get<MethodID::TYPE_INSTANCE>( | 33 MethodID::Get<MethodID::TYPE_INSTANCE>( |
30 env, throwable_clazz.obj(), "printStackTrace", | 34 env, throwable_clazz.obj(), "printStackTrace", |
31 "(Ljava/io/PrintStream;)V"); | 35 "(Ljava/io/PrintStream;)V"); |
32 | 36 |
33 // Create an instance of ByteArrayOutputStream. | 37 // Create an instance of ByteArrayOutputStream. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 | 115 |
112 void InitApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) { | 116 void InitApplicationContext(JNIEnv* env, const JavaRef<jobject>& context) { |
113 if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) { | 117 if (env->IsSameObject(g_application_context.Get().obj(), context.obj())) { |
114 // It's safe to set the context more than once if it's the same context. | 118 // It's safe to set the context more than once if it's the same context. |
115 return; | 119 return; |
116 } | 120 } |
117 DCHECK(g_application_context.Get().is_null()); | 121 DCHECK(g_application_context.Get().is_null()); |
118 g_application_context.Get().Reset(context); | 122 g_application_context.Get().Reset(context); |
119 } | 123 } |
120 | 124 |
125 void InitFallbackClassLoader(JNIEnv* env) { | |
126 DCHECK(g_class_loader.Get().is_null()); | |
127 | |
128 ScopedJavaLocalRef<jclass> class_loader_clazz = | |
129 GetClass(env, "java/lang/ClassLoader"); | |
130 g_class_loader_load_class_method_id = | |
131 env->GetMethodID(class_loader_clazz.obj(), | |
132 "loadClass", | |
133 "(Ljava/lang/String;)Ljava/lang/Class;"); | |
134 ScopedJavaLocalRef<jobject> class_loader = GetClassLoader(env); | |
mkosiba (inactive)
2014/08/15 16:53:50
having jni_android depend on jni initialization ha
| |
135 DCHECK(!class_loader.is_null()); | |
136 g_class_loader.Get().Reset(class_loader); | |
137 } | |
138 | |
121 const jobject GetApplicationContext() { | 139 const jobject GetApplicationContext() { |
122 DCHECK(!g_application_context.Get().is_null()); | 140 DCHECK(!g_application_context.Get().is_null()); |
123 return g_application_context.Get().obj(); | 141 return g_application_context.Get().obj(); |
124 } | 142 } |
125 | 143 |
126 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { | 144 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { |
127 jclass clazz = env->FindClass(class_name); | 145 jclass clazz; |
146 if (!g_class_loader.Get().is_null()) { | |
147 clazz = static_cast<jclass>( | |
148 env->CallObjectMethod(g_class_loader.Get().obj(), | |
149 g_class_loader_load_class_method_id, | |
150 ConvertUTF8ToJavaString(env, class_name).obj())); | |
151 } else { | |
152 clazz = env->FindClass(class_name); | |
153 } | |
128 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name; | 154 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name; |
129 return ScopedJavaLocalRef<jclass>(env, clazz); | 155 return ScopedJavaLocalRef<jclass>(env, clazz); |
130 } | 156 } |
131 | 157 |
158 jclass LazyGetClass( | |
159 JNIEnv* env, | |
160 const char* class_name, | |
161 base::subtle::AtomicWord* atomic_class_id) { | |
162 COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jclass), | |
163 AtomicWord_SmallerThan_jMethodID); | |
164 subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_class_id); | |
165 if (value) | |
166 return reinterpret_cast<jclass>(value); | |
167 ScopedJavaGlobalRef<jclass> clazz; | |
168 clazz.Reset(GetClass(env, class_name)); | |
169 subtle::AtomicWord null_aw = reinterpret_cast<subtle::AtomicWord>(NULL); | |
170 subtle::AtomicWord old = base::subtle::Release_CompareAndSwap( | |
171 atomic_class_id, | |
172 null_aw, | |
173 reinterpret_cast<subtle::AtomicWord>(clazz.obj())); | |
174 if (old == null_aw) { | |
175 // We intentionally release the global ref as that makes it easy to store | |
176 // the ref in |atomic_class_id|. | |
177 return clazz.Release(); | |
178 } else { | |
179 subtle::AtomicWord value = base::subtle::Release_Load(atomic_class_id); | |
180 CHECK(value); | |
181 return reinterpret_cast<jclass>(value); | |
182 } | |
183 } | |
184 | |
132 template<MethodID::Type type> | 185 template<MethodID::Type type> |
133 jmethodID MethodID::Get(JNIEnv* env, | 186 jmethodID MethodID::Get(JNIEnv* env, |
134 jclass clazz, | 187 jclass clazz, |
135 const char* method_name, | 188 const char* method_name, |
136 const char* jni_signature) { | 189 const char* jni_signature) { |
137 jmethodID id = type == TYPE_STATIC ? | 190 jmethodID id = type == TYPE_STATIC ? |
138 env->GetStaticMethodID(clazz, method_name, jni_signature) : | 191 env->GetStaticMethodID(clazz, method_name, jni_signature) : |
139 env->GetMethodID(clazz, method_name, jni_signature); | 192 env->GetMethodID(clazz, method_name, jni_signature); |
140 CHECK(base::android::ClearException(env) || id) << | 193 CHECK(base::android::ClearException(env) || id) << |
141 "Failed to find " << | 194 "Failed to find " << |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 base::android::BuildInfo::GetInstance()->set_java_exception_info( | 262 base::android::BuildInfo::GetInstance()->set_java_exception_info( |
210 GetJavaExceptionInfo(env, java_throwable)); | 263 GetJavaExceptionInfo(env, java_throwable)); |
211 } | 264 } |
212 | 265 |
213 // Now, feel good about it and die. | 266 // Now, feel good about it and die. |
214 CHECK(false) << "Please include Java exception stack in crash report"; | 267 CHECK(false) << "Please include Java exception stack in crash report"; |
215 } | 268 } |
216 | 269 |
217 } // namespace android | 270 } // namespace android |
218 } // namespace base | 271 } // namespace base |
OLD | NEW |