1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/java/jni_helper.h"
9 #include "base/android/jni_android.h"
10 #include "base/lazy_instance.h"
11 #include "base/threading/platform_thread.h"
17 struct MethodIdentifier {
18 const char* class_name;
20 const char* jni_signature;
22 bool operator<(const MethodIdentifier& other) const {
23 int r = strcmp(class_name, other.class_name);
30 r = strcmp(method, other.method);
37 return strcmp(jni_signature, other.jni_signature) < 0;
41 typedef std::map<MethodIdentifier, jmethodID> MethodIDMap;
43 const base::subtle::AtomicWord kUnlocked = 0;
44 const base::subtle::AtomicWord kLocked = 1;
45 base::subtle::AtomicWord g_method_id_map_lock = kUnlocked;
47 base::LazyInstance<MethodIDMap> g_method_id_map = LAZY_INSTANCE_INITIALIZER;
51 jfieldID GetFieldID(JNIEnv* env,
52 const base::android::JavaRef<jclass>& clazz,
53 const char* field_name,
54 const char* jni_signature) {
55 jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature);
56 CHECK(!base::android::ClearException(env) && field_id) <<
57 "Failed to find field " << field_name << " " << jni_signature;
61 jmethodID GetMethodIDFromClassName(JNIEnv* env,
62 const char* class_name,
64 const char* jni_signature) {
66 key.class_name = class_name;
68 key.jni_signature = jni_signature;
70 MethodIDMap* map = g_method_id_map.Pointer();
73 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
75 kLocked) != kUnlocked) {
76 base::PlatformThread::YieldCurrentThread();
78 MethodIDMap::const_iterator iter = map->find(key);
79 if (iter != map->end()) {
82 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
84 // Addition to the map does not invalidate this iterator.
89 base::android::ScopedJavaLocalRef<jclass> clazz(
90 env, env->FindClass(class_name));
91 jmethodID id = base::android::MethodID::Get<
92 base::android::MethodID::TYPE_INSTANCE>(
93 env, clazz.obj(), method, jni_signature);
95 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock,
97 kLocked) != kUnlocked) {
98 base::PlatformThread::YieldCurrentThread();
100 // Another thread may have populated the map already.
101 std::pair<MethodIDMap::const_iterator, bool> result =
102 map->insert(std::make_pair(key, id));
103 DCHECK_EQ(id, result.first->second);
104 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked);
109 } // namespace content