diff --git a/mobile/library/common/jni/android_jni_interface.cc b/mobile/library/common/jni/android_jni_interface.cc index a7f650492aec..504939170f24 100644 --- a/mobile/library/common/jni/android_jni_interface.cc +++ b/mobile/library/common/jni/android_jni_interface.cc @@ -12,7 +12,9 @@ extern "C" JNIEXPORT jint JNICALL Java_io_envoyproxy_envoymobile_engine_AndroidJniLibrary_initialize(JNIEnv* env, jclass, // class + jobject class_loader, jobject connectivity_manager) { + set_class_loader(env->NewGlobalRef(class_loader)); // See note above about c-ares. // c-ares jvm init is necessary in order to let c-ares perform DNS resolution in Envoy. // More information can be found at: diff --git a/mobile/library/common/jni/jni_utility.cc b/mobile/library/common/jni/jni_utility.cc index 0d9dbe427b85..5ed7247e0951 100644 --- a/mobile/library/common/jni/jni_utility.cc +++ b/mobile/library/common/jni/jni_utility.cc @@ -11,12 +11,29 @@ // NOLINT(namespace-envoy) static JavaVM* static_jvm = nullptr; +static jobject static_class_loader = nullptr; static thread_local JNIEnv* local_env = nullptr; void set_vm(JavaVM* vm) { static_jvm = vm; } JavaVM* get_vm() { return static_jvm; } +void set_class_loader(jobject class_loader) { static_class_loader = class_loader; } + +jobject get_class_loader() { return static_class_loader; } + +jclass find_class(const char* class_name) { + JNIEnv* env = get_env(); + jclass class_loader = env->FindClass("java/lang/ClassLoader"); + jmethodID find_class_method = + env->GetMethodID(class_loader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + jstring str_class_name = env->NewStringUTF(class_name); + jclass clazz = + (jclass)(env->CallObjectMethod(get_class_loader(), find_class_method, str_class_name)); + env->DeleteLocalRef(str_class_name); + return clazz; +} + JNIEnv* get_env() { if (local_env) { return local_env; diff --git a/mobile/library/common/jni/jni_utility.h b/mobile/library/common/jni/jni_utility.h index 3e1e4b0db064..159ab5a2802d 100644 --- a/mobile/library/common/jni/jni_utility.h +++ b/mobile/library/common/jni/jni_utility.h @@ -14,6 +14,25 @@ JavaVM* get_vm(); JNIEnv* get_env(); +void set_class_loader(jobject class_loader); + +/** + * Finds a class with a given name using a class loader provided with the use + * of `set_class_loader` function. The class loader is supposed to come from + * application's context and should be associated with project's code - Java classes + * defined by the project. For finding classes of Java built in-types use + * `env->FindClass(...)` method instead as it is lighter to use. + * + * The method works on Android targets only as the `set_class_loader` method is not + * called by JVM-only targets. + * + * @param class_name, the name of the class to find (i.e. "org.chromium.net.AndroidNetworkLibrary"). + * + * @return jclass, the class with a provided `class_name` or NULL if + * it couldn't be found. + */ +jclass find_class(const char* class_name); + void jvm_detach_thread(); void jni_delete_global_ref(void* context); diff --git a/mobile/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java b/mobile/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java index ee70d215e91c..02e7cf81581d 100644 --- a/mobile/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java +++ b/mobile/library/java/io/envoyproxy/envoymobile/engine/AndroidJniLibrary.java @@ -33,6 +33,7 @@ public static void load(Context context) { private static class AndroidLoader { private AndroidLoader(Context context) { AndroidJniLibrary.initialize( + context.getClassLoader(), (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE)); } } @@ -40,8 +41,10 @@ private AndroidLoader(Context context) { /** * Native binding to register the ConnectivityManager to C-Ares. * + * @param classLoader Application's class loader. * @param connectivityManager Android's ConnectivityManager. * @return The resulting status of the initialization. */ - protected static native int initialize(ConnectivityManager connectivityManager); + protected static native int initialize(ClassLoader classLoader, + ConnectivityManager connectivityManager); }