-
Notifications
You must be signed in to change notification settings - Fork 64
Open
Description
I had encountered a memory leak problem while debugging the initial version of android-usbser-rs
. A loop polling for USB transfer data causes the problem, and it crashed on older Android versions (< 8.0).
I did an experiement and realized that attach_current_thread_permanently()
prevents automatic de-allocation of JNI local references, unless making use of local frames or the AutoLocal
wrapper. Is there a solution with better performance?
- https://docs.rs/jni/latest/jni/struct.JNIEnv.html#references-and-lifetimes
- https://docs.rs/jni/latest/jni/struct.JNIEnv.html#method.auto_local
Test program:
[package]
name = "android-simple-test"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
jni = "0.21"
ndk-context = "0.1"
android-activity = { version = "0.6", features = ["native-activity"] }
[lib]
name = "android_simple_test"
crate-type = ["cdylib"]
path = "main.rs"
[package.metadata.android]
package = "com.example.android_simple_test"
build_targets = [ "aarch64-linux-android" ]
[package.metadata.android.sdk]
min_sdk_version = 16
target_sdk_version = 30
#[no_mangle]
fn android_main(_: android_activity::AndroidApp) {
let mut i: i32 = 0;
loop {
let _ = with_jni_env_ctx(|env, _| {
let _ = env.new_string(format!("test {}", i))
// .map(|o| env.auto_local(o))
.unwrap();
Ok(())
});
i = i.wrapping_add(1);
if i == 1000_000 {
println!("Not crashed");
}
}
}
use jni::errors::Error;
fn with_jni_env_ctx<R>(
f: impl FnOnce(&mut jni::JNIEnv, &jni::objects::JObject<'static>) -> Result<R, Error>,
) -> Result<R, Error> {
let ctx = ndk_context::android_context();
let jvm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }?;
let context = unsafe { jni::objects::JObject::from_raw(ctx.context().cast()) };
let mut env = jvm.attach_current_thread()?;
f(&mut env, &context)
}
It causes memory leak, and crashes on older Android versions:
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] JNI ERROR (app bug): local reference table overflow (max=512)
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] local reference table dump:
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] Last 10 entries (of 512):
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 511: 0x12d511a0 java.lang.String "test 511"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 510: 0x12d51180 java.lang.String "test 510"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 509: 0x12d51160 java.lang.String "test 509"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 508: 0x12d51140 java.lang.String "test 508"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 507: 0x12d51120 java.lang.String "test 507"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 506: 0x12d51100 java.lang.String "test 506"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 505: 0x12d510e0 java.lang.String "test 505"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 504: 0x12d510c0 java.lang.String "test 504"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 503: 0x12d510a0 java.lang.String "test 503"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 502: 0x12d51080 java.lang.String "test 502"
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] Summary:
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115] 512 of java.lang.String (512 unique instances)
11-16 01:49:21.761 16408 16422 F art : art/runtime/indirect_reference_table.cc:115]
11-16 01:49:21.765 16408 16421 I RustStdoutStderr: referenceTable GDEF length=814 1
11-16 01:49:21.765 16408 16421 I RustStdoutStderr: referenceTable GSUB length=11364 1
11-16 01:49:21.765 16408 16421 I RustStdoutStderr: referenceTable GPOS length=47302 1
11-16 01:49:21.778 856 1849 D audio_hw_primary: start_output_stream: exit
11-16 01:49:21.813 16408 16422 F art : art/runtime/barrier.cc:90] Check failed: count_ == 0 (count_=-1, 0=0) Attempted to destroy barrier with non zero count
11-16 01:49:21.813 16408 16422 F art : art/runtime/runtime.cc:366] Runtime aborting --- recursively, so no thread-specific detail!
11-16 01:49:21.813 16408 16422 F art : art/runtime/runtime.cc:366]
--------- beginning of crash
11-16 01:49:21.813 16408 16422 F libc : Fatal signal 6 (SIGABRT), code -6 in tid 16422 (android_main)
Put the loop in another thread, do not attach it to the JVM permanantly, then you'll not have this problem.
PS: would you like to check this issue (not important): mzdk100/droid-wrap#2.
Metadata
Metadata
Assignees
Labels
No labels