From e65d4c44b4ded4cb50fe37d8d811feba7f2266a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Mon, 30 Mar 2026 10:11:39 +0200 Subject: [PATCH] fix(ffi): Replace `libloading` with `jvm-getter` for getting a JVM The `libloading` approach only works on Android 12+ --- Cargo.lock | 113 ++++++++++++++++-- bindings/matrix-sdk-ffi/CHANGELOG.md | 3 + bindings/matrix-sdk-ffi/Cargo.toml | 4 +- .../src/platform/android_platform.rs | 34 ++---- 4 files changed, 117 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b235445e4..160c25aa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2169,6 +2169,17 @@ dependencies = [ "scroll", ] +[[package]] +name = "goblin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa0a64d21a7eb230583b4c5f4e23b7e4e57974f96620f42a7e75e08ae66d745" +dependencies = [ + "log", + "plain", + "scroll", +] + [[package]] name = "growable-bloom-filter" version = "2.1.1" @@ -2910,6 +2921,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jvm-getter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9353d43a802ba22de0de749f4aa51f3414a6a9b5037559eaac65584db65218" +dependencies = [ + "goblin 0.9.3", + "jni-sys", + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "konst" version = "0.3.9" @@ -2957,16 +2980,6 @@ version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" -[[package]] -name = "libloading" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" -dependencies = [ - "cfg-if", - "windows-link 0.2.1", -] - [[package]] name = "libm" version = "0.2.15" @@ -3444,8 +3457,8 @@ dependencies = [ "futures-executor", "futures-util", "jni", + "jvm-getter", "language-tags", - "libloading", "log-panics", "matrix-sdk", "matrix-sdk-base", @@ -6645,7 +6658,7 @@ dependencies = [ "cargo_metadata", "fs-err", "glob", - "goblin", + "goblin 0.8.2", "heck", "indexmap", "once_cell", @@ -7351,6 +7364,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -7399,13 +7421,30 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + [[package]] name = "windows-threading" version = "0.1.0" @@ -7433,6 +7472,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7451,6 +7496,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -7469,12 +7520,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -7493,6 +7556,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -7511,6 +7580,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -7529,6 +7604,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -7547,6 +7628,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.6.20" diff --git a/bindings/matrix-sdk-ffi/CHANGELOG.md b/bindings/matrix-sdk-ffi/CHANGELOG.md index 574125080..00966f7fe 100644 --- a/bindings/matrix-sdk-ffi/CHANGELOG.md +++ b/bindings/matrix-sdk-ffi/CHANGELOG.md @@ -8,6 +8,9 @@ All notable changes to this project will be documented in this file. ### Bug Fixes +- Fix devices on Android 11 crashing because the SDK could not be initialized using `libloading` + to get a reference to the JVM. Replaced `libloading` with `jvm-getter`, which works like a + compatibility layer. ([#6370](https://github.com/matrix-org/matrix-rust-sdk/pull/6370)) - Added `android_platform.rs` for fixing the `rustls` integration on Android, which was broken. ([#6306](https://github.com/matrix-org/matrix-rust-sdk/pull/6306)) - [**breaking**] `OtherState` properly supports redacted events that still have fields in the diff --git a/bindings/matrix-sdk-ffi/Cargo.toml b/bindings/matrix-sdk-ffi/Cargo.toml index 7960c80ac..aa425b771 100644 --- a/bindings/matrix-sdk-ffi/Cargo.toml +++ b/bindings/matrix-sdk-ffi/Cargo.toml @@ -128,10 +128,10 @@ paranoid-android = { version = "0.2.2", default-features = false } jni = "0.21.1" # Used to access the credential storage on Android rustls-platform-verifier = "0.6.2" -# Used to avoid having to call an exposed JNI call from the Android client to initialize `rustls-platform-verifier` -libloading = "0.9.0" # Needed for intializing and keeping the JavaVM reference around once_cell = "1.21.4" +# Gobley's jvm-getter is used to get a JVM pointer from all Android versions +jvm-getter = "0.1.0" [dev-dependencies] similar-asserts.workspace = true diff --git a/bindings/matrix-sdk-ffi/src/platform/android_platform.rs b/bindings/matrix-sdk-ffi/src/platform/android_platform.rs index 2eaf7ace7..6a6d9f861 100644 --- a/bindings/matrix-sdk-ffi/src/platform/android_platform.rs +++ b/bindings/matrix-sdk-ffi/src/platform/android_platform.rs @@ -1,8 +1,8 @@ -use std::error::Error; +use std::{error::Error, mem::MaybeUninit}; use jni::{ errors::JniError, - sys::{jint, jsize, JavaVM}, + sys::{JavaVM as RawJavaVM, JNI_OK}, }; use tracing::debug; @@ -34,30 +34,20 @@ pub(crate) fn init() { }); } -type JniGetCreatedJavaVms = - unsafe extern "system" fn(_: *mut *mut JavaVM, _: jsize, _: *mut jsize) -> jint; -const JNI_GET_JAVA_VMS_NAME: &[u8] = b"JNI_GetCreatedJavaVMs"; - fn get_java_vm() -> Result> { - // Use libloading to avoid having to create and expose a JNI function and call - // it from the Android side. - let library = libloading::os::unix::Library::this(); - let get_created_java_vms: JniGetCreatedJavaVms = - unsafe { *library.get(JNI_GET_JAVA_VMS_NAME)? }; + debug!("Getting a JVM pointer"); + #[allow(non_snake_case)] + let JNI_GetCreatedJavaVMs = unsafe { + jvm_getter::find_jni_get_created_java_vms().expect("Failed to find JNI_GetCreatedJavaVMs") + }; - let mut java_vms: [*mut JavaVM; 1] = [std::ptr::null_mut() as *mut JavaVM]; - let mut vm_count: i32 = 0; - - let ok = unsafe { get_created_java_vms(java_vms.as_mut_ptr(), 1, &mut vm_count) }; - if ok != jni::sys::JNI_OK { - return Err("Failed to get JavaVM".into()); - } - if vm_count != 1 { - return Err(format!("Invalid JavaVM count: {vm_count}").into()); + let mut vm: MaybeUninit<*mut RawJavaVM> = MaybeUninit::uninit(); + let status = unsafe { JNI_GetCreatedJavaVMs(vm.as_mut_ptr(), 1, &mut 0) }; + if status != JNI_OK { + panic!("no JavaVM was found by JNI_GetCreatedJavaVMs"); } - let jvm = unsafe { jni::JavaVM::from_raw(java_vms[0]) }?; - Ok(jvm) + unsafe { jni::JavaVM::from_raw(vm.assume_init()).map_err(|e| e.into()) } } fn init_rustls_platform_verifier(env: &mut jni::JNIEnv<'_>) -> jni::errors::Result<()> {