Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(605)

Side by Side Diff: base/android/jni_android.cc

Issue 23835020: Android: cleanup jni_android to minimize external dependencies. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/threading/platform_thread.h"
14 13
15 namespace { 14 namespace {
16 using base::android::GetClass; 15 using base::android::GetClass;
17 using base::android::MethodID; 16 using base::android::MethodID;
18 using base::android::ScopedJavaLocalRef; 17 using base::android::ScopedJavaLocalRef;
19 18
20 struct MethodIdentifier {
21 const char* class_name;
22 const char* method;
23 const char* jni_signature;
24
25 bool operator<(const MethodIdentifier& other) const {
26 int r = strcmp(class_name, other.class_name);
27 if (r < 0) {
28 return true;
29 } else if (r > 0) {
30 return false;
31 }
32
33 r = strcmp(method, other.method);
34 if (r < 0) {
35 return true;
36 } else if (r > 0) {
37 return false;
38 }
39
40 return strcmp(jni_signature, other.jni_signature) < 0;
41 }
42 };
43
44 typedef std::map<MethodIdentifier, jmethodID> MethodIDMap;
45
46 const base::subtle::AtomicWord kUnlocked = 0;
47 const base::subtle::AtomicWord kLocked = 1;
48 base::subtle::AtomicWord g_method_id_map_lock = kUnlocked;
49 JavaVM* g_jvm = NULL; 19 JavaVM* g_jvm = NULL;
50 // Leak the global app context, as it is used from a non-joinable worker thread 20 // Leak the global app context, as it is used from a non-joinable worker thread
51 // that may still be running at shutdown. There is no harm in doing this. 21 // that may still be running at shutdown. There is no harm in doing this.
52 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky 22 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> >::Leaky
53 g_application_context = LAZY_INSTANCE_INITIALIZER; 23 g_application_context = LAZY_INSTANCE_INITIALIZER;
54 base::LazyInstance<MethodIDMap> g_method_id_map = LAZY_INSTANCE_INITIALIZER;
55 24
56 std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) { 25 std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) {
57 ScopedJavaLocalRef<jclass> throwable_clazz = 26 ScopedJavaLocalRef<jclass> throwable_clazz =
58 GetClass(env, "java/lang/Throwable"); 27 GetClass(env, "java/lang/Throwable");
59 jmethodID throwable_printstacktrace = 28 jmethodID throwable_printstacktrace =
60 MethodID::Get<MethodID::TYPE_INSTANCE>( 29 MethodID::Get<MethodID::TYPE_INSTANCE>(
61 env, throwable_clazz.obj(), "printStackTrace", 30 env, throwable_clazz.obj(), "printStackTrace",
62 "(Ljava/io/PrintStream;)V"); 31 "(Ljava/io/PrintStream;)V");
63 32
64 // Create an instance of ByteArrayOutputStream. 33 // Create an instance of ByteArrayOutputStream.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 DCHECK(!g_application_context.Get().is_null()); 106 DCHECK(!g_application_context.Get().is_null());
138 return g_application_context.Get().obj(); 107 return g_application_context.Get().obj();
139 } 108 }
140 109
141 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { 110 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) {
142 jclass clazz = env->FindClass(class_name); 111 jclass clazz = env->FindClass(class_name);
143 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name; 112 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name;
144 return ScopedJavaLocalRef<jclass>(env, clazz); 113 return ScopedJavaLocalRef<jclass>(env, clazz);
145 } 114 }
146 115
147 bool HasClass(JNIEnv* env, const char* class_name) {
148 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name));
149 if (!clazz.obj()) {
150 ClearException(env);
151 return false;
152 }
153 bool error = ClearException(env);
154 DCHECK(!error);
155 return true;
156 }
157
158 template<MethodID::Type type> 116 template<MethodID::Type type>
159 jmethodID MethodID::Get(JNIEnv* env, 117 jmethodID MethodID::Get(JNIEnv* env,
160 jclass clazz, 118 jclass clazz,
161 const char* method_name, 119 const char* method_name,
162 const char* jni_signature) { 120 const char* jni_signature) {
163 jmethodID id = type == TYPE_STATIC ? 121 jmethodID id = type == TYPE_STATIC ?
164 env->GetStaticMethodID(clazz, method_name, jni_signature) : 122 env->GetStaticMethodID(clazz, method_name, jni_signature) :
165 env->GetMethodID(clazz, method_name, jni_signature); 123 env->GetMethodID(clazz, method_name, jni_signature);
166 CHECK(base::android::ClearException(env) || id) << 124 CHECK(base::android::ClearException(env) || id) <<
167 "Failed to find " << 125 "Failed to find " <<
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 const char* jni_signature); 158 const char* jni_signature);
201 159
202 template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>( 160 template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
203 JNIEnv* env, jclass clazz, const char* method_name, 161 JNIEnv* env, jclass clazz, const char* method_name,
204 const char* jni_signature, base::subtle::AtomicWord* atomic_method_id); 162 const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
205 163
206 template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>( 164 template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
207 JNIEnv* env, jclass clazz, const char* method_name, 165 JNIEnv* env, jclass clazz, const char* method_name,
208 const char* jni_signature, base::subtle::AtomicWord* atomic_method_id); 166 const char* jni_signature, base::subtle::AtomicWord* atomic_method_id);
209 167
210 jfieldID GetFieldID(JNIEnv* env,
211 const JavaRef<jclass>& clazz,
212 const char* field_name,
213 const char* jni_signature) {
214 jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature);
215 CHECK(!ClearException(env) && field_id) << "Failed to find field " <<
216 field_name << " " << jni_signature;
217 return field_id;
218 }
219
220 bool HasField(JNIEnv* env,
221 const JavaRef<jclass>& clazz,
222 const char* field_name,
223 const char* jni_signature) {
224 jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature);
225 if (!field_id) {
226 ClearException(env);
227 return false;
228 }
229 bool error = ClearException(env);
230 DCHECK(!error);
231 return true;
232 }
233
234 jfieldID GetStaticFieldID(JNIEnv* env,
235 const JavaRef<jclass>& clazz,
236 const char* field_name,
237 const char* jni_signature) {
238 jfieldID field_id =
239 env->GetStaticFieldID(clazz.obj(), field_name, jni_signature);
240 CHECK(!ClearException(env) && field_id) << "Failed to find static field " <<
241 field_name << " " << jni_signature;
242 return field_id;
243 }
244
245 jmethodID GetMethodIDFromClassName(JNIEnv* env,
246 const char* class_name,
247 const char* method,
248 const char* jni_signature) {
249 MethodIdentifier key;
250 key.class_name = class_name;
251 key.method = method;
252 key.jni_signature = jni_signature;
253
254 MethodIDMap* map = g_method_id_map.Pointer();
255 bool found = false;
256
257 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
258 kUnlocked,
259 kLocked) != kUnlocked) {
260 base::PlatformThread::YieldCurrentThread();
261 }
262 MethodIDMap::const_iterator iter = map->find(key);
263 if (iter != map->end()) {
264 found = true;
265 }
266 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
267
268 // Addition to the map does not invalidate this iterator.
269 if (found) {
270 return iter->second;
271 }
272
273 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name));
274 jmethodID id = MethodID::Get<MethodID::TYPE_INSTANCE>(
275 env, clazz.obj(), method, jni_signature);
276
277 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
278 kUnlocked,
279 kLocked) != kUnlocked) {
280 base::PlatformThread::YieldCurrentThread();
281 }
282 // Another thread may have populated the map already.
283 std::pair<MethodIDMap::const_iterator, bool> result =
284 map->insert(std::make_pair(key, id));
285 DCHECK_EQ(id, result.first->second);
286 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
287
288 return id;
289 }
290
291 bool HasException(JNIEnv* env) { 168 bool HasException(JNIEnv* env) {
292 return env->ExceptionCheck() != JNI_FALSE; 169 return env->ExceptionCheck() != JNI_FALSE;
293 } 170 }
294 171
295 bool ClearException(JNIEnv* env) { 172 bool ClearException(JNIEnv* env) {
296 if (!HasException(env)) 173 if (!HasException(env))
297 return false; 174 return false;
298 env->ExceptionDescribe(); 175 env->ExceptionDescribe();
299 env->ExceptionClear(); 176 env->ExceptionClear();
300 return true; 177 return true;
(...skipping 17 matching lines...) Expand all
318 // RVO should avoid any extra copies of the exception string. 195 // RVO should avoid any extra copies of the exception string.
319 base::android::BuildInfo::GetInstance()->set_java_exception_info( 196 base::android::BuildInfo::GetInstance()->set_java_exception_info(
320 GetJavaExceptionInfo(env, java_throwable)); 197 GetJavaExceptionInfo(env, java_throwable));
321 198
322 // Now, feel good about it and die. 199 // Now, feel good about it and die.
323 CHECK(false); 200 CHECK(false);
324 } 201 }
325 202
326 } // namespace android 203 } // namespace android
327 } // namespace base 204 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698