manganis: load FFI classes from the activity classloader, not FindClass
JNIEnv::find_class resolves against the system classloader on a thread attached from native code, which cannot see APK classes (#5629). Route the generated #[manganis::ffi] type lookup through load_class_from_classloader, and reimplement that helper to ask the activity's own ClassLoader.loadClass instead of Class.forName.
This commit is contained in:
1 parent
07dddd569e
commit
aeb5568727
2 files changed
+25
-6
No files matched your search
@@ -398,7 +398,7 @@ impl FfiBridgeParser {
|
||||
// Use with_activity which returns Option<R>, wrapping our Result in the Option
|
||||
let inner_result: Option<Result<Self, String>> = manganis::android::with_activity(|mut env, activity| {
|
||||
// Find the class
|
||||
let class_result = env.find_class(#class_name_lit);
|
||||
let class_result = manganis::android::load_class_from_classloader(env, activity, #class_name_lit);
|
||||
let class = match class_result {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Some(Err(format!("Failed to find class {}: {:?}", #class_name_lit, e))),
|
||||
|
||||
@@ -111,15 +111,34 @@ pub fn request_permissions_via_helper(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load a Java class from the APK's classloader
|
||||
/// Load a Java class from the APK's classloader.
|
||||
///
|
||||
/// `JNIEnv::find_class` resolves against the *system* classloader on a thread that
|
||||
/// was attached from native code (`JavaVM::attach_current_thread`), which cannot see
|
||||
/// classes packaged in the APK, so it raises `ClassNotFoundException`. The activity's
|
||||
/// own classloader can, so we ask the activity for it and call `loadClass` on it.
|
||||
///
|
||||
/// `class_name` may be given in either JNI form (`com/example/Foo`) or binary form
|
||||
/// (`com.example.Foo`); `loadClass` requires the binary form, so slashes are converted.
|
||||
pub fn load_class_from_classloader<'env>(
|
||||
env: &mut JNIEnv<'env>,
|
||||
activity: &JObject<'_>,
|
||||
class_name: &str,
|
||||
) -> Result<JClass<'env>> {
|
||||
let class_name_jstring = new_string(env, class_name)?;
|
||||
let class = env.call_static_method(
|
||||
"java/lang/Class",
|
||||
"forName",
|
||||
let binary_name = class_name.replace('/', ".");
|
||||
let activity_class = env.get_object_class(activity)?;
|
||||
let loader = env
|
||||
.call_method(
|
||||
&activity_class,
|
||||
"getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;",
|
||||
&[],
|
||||
)?
|
||||
.l()?;
|
||||
let class_name_jstring = new_string(env, &binary_name)?;
|
||||
let class = env.call_method(
|
||||
&loader,
|
||||
"loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;",
|
||||
&[JValue::Object(&class_name_jstring)],
|
||||
)?;
|
||||
|
||||
Reference in new issue
Block a user