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

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

Issue 491043002: Make class lookup lazy in jni_generator when using lazy method lookup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 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
« no previous file with comments | « base/android/jni_android.h ('k') | base/android/jni_generator/golden_sample_for_tests_jni.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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 InitReplacementClassLoader(JNIEnv* env,
126 const JavaRef<jobject>& class_loader) {
127 DCHECK(g_class_loader.Get().is_null());
128 DCHECK(!class_loader.is_null());
129
130 ScopedJavaLocalRef<jclass> class_loader_clazz =
131 GetClass(env, "java/lang/ClassLoader");
132 CHECK(!ClearException(env));
133 g_class_loader_load_class_method_id =
134 env->GetMethodID(class_loader_clazz.obj(),
135 "loadClass",
136 "(Ljava/lang/String;)Ljava/lang/Class;");
137 CHECK(!ClearException(env));
138
139 DCHECK(env->IsInstanceOf(class_loader.obj(), class_loader_clazz.obj()));
140 g_class_loader.Get().Reset(class_loader);
141 }
142
121 const jobject GetApplicationContext() { 143 const jobject GetApplicationContext() {
122 DCHECK(!g_application_context.Get().is_null()); 144 DCHECK(!g_application_context.Get().is_null());
123 return g_application_context.Get().obj(); 145 return g_application_context.Get().obj();
124 } 146 }
125 147
126 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { 148 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) {
127 jclass clazz = env->FindClass(class_name); 149 jclass clazz;
150 if (!g_class_loader.Get().is_null()) {
151 clazz = static_cast<jclass>(
152 env->CallObjectMethod(g_class_loader.Get().obj(),
153 g_class_loader_load_class_method_id,
154 ConvertUTF8ToJavaString(env, class_name).obj()));
155 } else {
156 clazz = env->FindClass(class_name);
157 }
128 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name; 158 CHECK(!ClearException(env) && clazz) << "Failed to find class " << class_name;
129 return ScopedJavaLocalRef<jclass>(env, clazz); 159 return ScopedJavaLocalRef<jclass>(env, clazz);
130 } 160 }
131 161
162 jclass LazyGetClass(
163 JNIEnv* env,
164 const char* class_name,
165 base::subtle::AtomicWord* atomic_class_id) {
166 COMPILE_ASSERT(sizeof(subtle::AtomicWord) >= sizeof(jclass),
167 AtomicWord_SmallerThan_jMethodID);
168 subtle::AtomicWord value = base::subtle::Acquire_Load(atomic_class_id);
169 if (value)
170 return reinterpret_cast<jclass>(value);
171 ScopedJavaGlobalRef<jclass> clazz;
172 clazz.Reset(GetClass(env, class_name));
173 subtle::AtomicWord null_aw = reinterpret_cast<subtle::AtomicWord>(NULL);
174 subtle::AtomicWord cas_result = base::subtle::Release_CompareAndSwap(
175 atomic_class_id,
176 null_aw,
177 reinterpret_cast<subtle::AtomicWord>(clazz.obj()));
178 if (cas_result == null_aw) {
179 // We intentionally leak the global ref since we now storing it as a raw
180 // pointer in |atomic_class_id|.
181 return clazz.Release();
182 } else {
183 return reinterpret_cast<jclass>(cas_result);
184 }
185 }
186
132 template<MethodID::Type type> 187 template<MethodID::Type type>
133 jmethodID MethodID::Get(JNIEnv* env, 188 jmethodID MethodID::Get(JNIEnv* env,
134 jclass clazz, 189 jclass clazz,
135 const char* method_name, 190 const char* method_name,
136 const char* jni_signature) { 191 const char* jni_signature) {
137 jmethodID id = type == TYPE_STATIC ? 192 jmethodID id = type == TYPE_STATIC ?
138 env->GetStaticMethodID(clazz, method_name, jni_signature) : 193 env->GetStaticMethodID(clazz, method_name, jni_signature) :
139 env->GetMethodID(clazz, method_name, jni_signature); 194 env->GetMethodID(clazz, method_name, jni_signature);
140 CHECK(base::android::ClearException(env) || id) << 195 CHECK(base::android::ClearException(env) || id) <<
141 "Failed to find " << 196 "Failed to find " <<
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 base::android::BuildInfo::GetInstance()->set_java_exception_info( 264 base::android::BuildInfo::GetInstance()->set_java_exception_info(
210 GetJavaExceptionInfo(env, java_throwable)); 265 GetJavaExceptionInfo(env, java_throwable));
211 } 266 }
212 267
213 // Now, feel good about it and die. 268 // Now, feel good about it and die.
214 CHECK(false) << "Please include Java exception stack in crash report"; 269 CHECK(false) << "Please include Java exception stack in crash report";
215 } 270 }
216 271
217 } // namespace android 272 } // namespace android
218 } // namespace base 273 } // namespace base
OLDNEW
« no previous file with comments | « base/android/jni_android.h ('k') | base/android/jni_generator/golden_sample_for_tests_jni.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698