Skip to content

Possible memory leakage and unhandled exception #2

Description

@wuwbobo2021

Possible memory leakage

Test program:

[package]
name = "droid-wrap-min-test"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
android-activity = { version = "0.6", features = ["native-activity"] }
droid-wrap-derive = { path = "../derive" }
droid-wrap-utils = { path = "../utils" }

[lib]
name = "droid_wrap_min_test"
crate-type = ["cdylib"]
path = "main.rs"

[package.metadata.android]
package = "com.example.droid_wrap_min_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) {
    loop {
        droid_wrap_utils::vm_attach!(mut env);
        let _ = droid_wrap_utils::wrapper_long_value(3, &mut env);
    }
}

Similar operations may work on PC systems (local references can be freed when env is droped and the thread is detached from JVM). However, it can be different on Android. Please run it on your device and check the RAM usage increment.

In fact it crashes under Android 7.0 (and below):

11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115] JNI ERROR (app bug): local reference table overflow (max=512)
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115] local reference table dump:
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]   Last 10 entries (of 511):
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       510: 0x12d52140 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       509: 0x12d52130 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       508: 0x12d52120 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       507: 0x12d52110 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       506: 0x12d52100 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       505: 0x12d520f0 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       504: 0x12d520e0 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       503: 0x12d520d0 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       502: 0x12d520c0 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       501: 0x12d520b0 java.lang.Long
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]   Summary:
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115]       511 of java.lang.Long (511 unique instances)
11-16 05:27:09.408 18430 18444 F art     : art/runtime/indirect_reference_table.cc:115] 
11-16 05:27:09.408 18430 18443 I RustStdoutStderr: referenceTable GDEF length=814 1
11-16 05:27:09.408 18430 18443 I RustStdoutStderr: referenceTable GSUB length=11364 1
11-16 05:27:09.408 18430 18443 I RustStdoutStderr: referenceTable GPOS length=47302 1
11-16 05:27:09.433   856  1849 D audio_hw_primary: start_output_stream: exit
11-16 05:27:09.468 18430 18444 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 05:27:09.468 18430 18444 F art     : art/runtime/runtime.cc:366] Runtime aborting --- recursively, so no thread-specific detail!
11-16 05:27:09.468 18430 18444 F art     : art/runtime/runtime.cc:366] 
--------- beginning of crash
11-16 05:27:09.468 18430 18444 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 18444 (android_main)

a possible way to fix it (however, if it were to be done, there would be lots of other places to be changed):

pub fn wrapper_long_value(value: i64, env: &mut JNIEnv) -> GlobalRef {
    let obj = env
        .new_object("java/lang/Long", "(J)V", &[value.into()])
        .map(|o| env.auto_local(o)) // Added
        .unwrap();
    env.new_global_ref(&obj).unwrap()
}

Possible unhandled exception

I have realized the ambition behind this project, but it's undocumented that how to use derive macros on Java functions with non-primitive object parameters. And I don't how Java exceptions are handled in this library.

The jni-rs problem described below happens on both PC and Android. Here's a test program on PC:

[package]
name = "jni-env"
version = "0.1.0"
edition = "2021"

[dependencies]
jni = { version = "0.21.1", features = ["invocation"] }
fn main() {
    let args = jni::InitArgsBuilder::new()
        .version(jni::JNIVersion::V8)
        .build()
        .unwrap();
    let vm = JavaVM::new(args).unwrap();
    let mut env = vm.attach_current_thread().unwrap();
    println!("{:?}", java_parse_int(&mut env, "3"));
    println!("{:?}", java_parse_int(&mut env, "s"));
    println!("{:?}", java_parse_int(&mut env, "5"));
}

fn java_parse_int(env: &mut JNIEnv, s: &str) -> Result<i32, Error> {
    let java_string = env.new_string(s).unwrap();
    env.call_static_method(
        "java/lang/Integer",
        "parseInt",
        "(Ljava/lang/String;)I",
        &[(&java_string).into()]
    )
    .map_err(|e| { env.exception_clear().unwrap(); e })
    .and_then(|o| o.i())
}

Output:

Ok(3)
Err(JavaException)
Ok(5)

After commenting .map_err(|e| { env.exception_clear().unwrap(); e }), it would crash on the third java_parse_int():

Ok(3)
Err(JavaException)
thread 'main' panicked at src/main.rs:21:41:
called `Result::unwrap()` on an `Err` value: JavaException
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "s"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Integer.parseInt(Integer.java:580)
        at java.lang.Integer.parseInt(Integer.java:615)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions