Skip to content

Commit

Permalink
jni: introduce custom find_class method (#2483)
Browse files Browse the repository at this point in the history
Description: The change is needed in order for JNI to be able to find classes which are defined in our repository (as opposed to built in Java types). Google documents in here touches on this issue. The implementation could be improved by adding some caching to it but I am inclined to keep it simple unless we find out that its performance is an issue. Needed for #2432.
Risk Level: None, not used anywhere as of now.
Testing: Manual
Docs Changes: N/A
Release Notes: N/A

Signed-off-by: Rafal Augustyniak [email protected]
Signed-off-by: JP Simard <[email protected]>
  • Loading branch information
Augustyniak authored and jpsim committed Nov 29, 2022
1 parent 40336fc commit a1fc669
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
2 changes: 2 additions & 0 deletions mobile/library/common/jni/android_jni_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
17 changes: 17 additions & 0 deletions mobile/library/common/jni/jni_utility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 19 additions & 0 deletions mobile/library/common/jni/jni_utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ public static void load(Context context) {
private static class AndroidLoader {
private AndroidLoader(Context context) {
AndroidJniLibrary.initialize(
context.getClassLoader(),
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE));
}
}

/**
* 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);
}

0 comments on commit a1fc669

Please sign in to comment.