• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "sdk/android/native_api/jni/class_loader.h"
12 
13 #include <algorithm>
14 #include <string>
15 
16 #include "rtc_base/checks.h"
17 #include "sdk/android/generated_native_api_jni/WebRtcClassLoader_jni.h"
18 #include "sdk/android/native_api/jni/java_types.h"
19 #include "sdk/android/native_api/jni/scoped_java_ref.h"
20 
21 // Abort the process if |jni| has a Java exception pending. This macros uses the
22 // comma operator to execute ExceptionDescribe and ExceptionClear ignoring their
23 // return values and sending "" to the error stream.
24 #define CHECK_EXCEPTION(jni)        \
25   RTC_CHECK(!jni->ExceptionCheck()) \
26       << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
27 
28 namespace webrtc {
29 
30 namespace {
31 
32 class ClassLoader {
33  public:
ClassLoader(JNIEnv * env)34   explicit ClassLoader(JNIEnv* env)
35       : class_loader_(jni::Java_WebRtcClassLoader_getClassLoader(env)) {
36     class_loader_class_ = reinterpret_cast<jclass>(
37         env->NewGlobalRef(env->FindClass("java/lang/ClassLoader")));
38     CHECK_EXCEPTION(env);
39     load_class_method_ =
40         env->GetMethodID(class_loader_class_, "loadClass",
41                          "(Ljava/lang/String;)Ljava/lang/Class;");
42     CHECK_EXCEPTION(env);
43   }
44 
FindClass(JNIEnv * env,const char * c_name)45   ScopedJavaLocalRef<jclass> FindClass(JNIEnv* env, const char* c_name) {
46     // ClassLoader.loadClass expects a classname with components separated by
47     // dots instead of the slashes that JNIEnv::FindClass expects.
48     std::string name(c_name);
49     std::replace(name.begin(), name.end(), '/', '.');
50     ScopedJavaLocalRef<jstring> j_name = NativeToJavaString(env, name);
51     const jclass clazz = static_cast<jclass>(env->CallObjectMethod(
52         class_loader_.obj(), load_class_method_, j_name.obj()));
53     CHECK_EXCEPTION(env);
54     return ScopedJavaLocalRef<jclass>(env, clazz);
55   }
56 
57  private:
58   ScopedJavaGlobalRef<jobject> class_loader_;
59   jclass class_loader_class_;
60   jmethodID load_class_method_;
61 };
62 
63 static ClassLoader* g_class_loader = nullptr;
64 
65 }  // namespace
66 
InitClassLoader(JNIEnv * env)67 void InitClassLoader(JNIEnv* env) {
68   RTC_CHECK(g_class_loader == nullptr);
69   g_class_loader = new ClassLoader(env);
70 }
71 
GetClass(JNIEnv * env,const char * name)72 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* name) {
73   // The class loader will be null in the JNI code called from the ClassLoader
74   // ctor when we are bootstrapping ourself.
75   return (g_class_loader == nullptr)
76              ? ScopedJavaLocalRef<jclass>(env, env->FindClass(name))
77              : g_class_loader->FindClass(env, name);
78 }
79 
80 }  // namespace webrtc
81