jni-simple 0.4.0

Simple Rust binding for JNI (Java Native Interface) and JVMTI (JVM Tool Interface)
Documentation
#[cfg(not(miri))]
#[cfg(feature = "loadjvm")]
#[cfg(feature = "std")]
pub mod test {
    use jni_simple::{JNI_CreateJavaVM_with_string_args, JNI_VERSION_1_8, JVMTI_VERSION_1_2, JVMTIEnv, load_jvm_from_java_home};
    use std::sync::Mutex;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering::SeqCst;
    use std::thread;
    use std::thread::ThreadId;
    use std::time::Duration;

    static STATE: Mutex<Option<ThreadId>> = Mutex::new(None);
    static FAILED: AtomicBool = AtomicBool::new(false);
    #[test]
    pub fn test() {
        unsafe {
            load_jvm_from_java_home().expect("failed to load jvm");
            let args: Vec<String> = vec![];
            let (vm, env) = JNI_CreateJavaVM_with_string_args(JNI_VERSION_1_8, &args, false).expect("failed to create java VM");
            let jvmti = vm.GetEnv::<JVMTIEnv>(JVMTI_VERSION_1_2).expect("Failed to get jvmti env");
            let thread_class = env.FindClass("java/lang/Thread");
            let thread_constructor = env.GetMethodID(thread_class, "<init>", "()V");
            let virign_thread = env.NewObject0(thread_class, thread_constructor);

            let mut jvmti_version = 0;
            assert!(jvmti.GetVersionNumber(&raw mut jvmti_version).is_ok());
            let jni_version = env.GetVersion();

            jvmti
                .RunAgentThread_fn(virign_thread, 1, move |jvmti, env| {
                    let jni_version_2 = env.GetVersion();
                    let mut jvmti_version_2 = 0;
                    if jvmti.GetVersionNumber(&raw mut jvmti_version_2).is_err() {
                        FAILED.store(true, SeqCst);
                    }

                    if jvmti_version_2 != jvmti_version {
                        FAILED.store(true, SeqCst);
                    }

                    if jni_version_2 != jni_version {
                        FAILED.store(true, SeqCst);
                    }

                    let mut g = STATE.lock().unwrap();
                    *g = Some(std::thread::current().id());
                    drop(g);
                })
                .expect("Failed to start thread");

            let oid = loop {
                thread::sleep(Duration::from_millis(100));
                if FAILED.load(SeqCst) {
                    panic!("Agent thread failed");
                }
                let st = STATE.lock().unwrap();
                if st.is_none() {
                    continue;
                }
                break st.unwrap().clone();
            };

            if FAILED.load(SeqCst) {
                panic!("Agent thread failed");
            }

            assert_ne!(thread::current().id(), oid);
        }
    }
}