coffee_roast/
java_vm.rs

1use crate::error::jni_error_code_to_result;
2use crate::sys;
3use std::path::PathBuf;
4use std::ptr;
5
6#[repr(transparent)]
7#[derive(Debug, Clone)]
8pub struct JavaVMInitArgs {
9    args: sys::JavaVMInitArgs,
10}
11
12impl Default for JavaVMInitArgs {
13    fn default() -> Self {
14        JavaVMInitArgs {
15            args: sys::JavaVMInitArgs {
16                version: sys::JNI_VERSION_1_8,
17                nOptions: 0,
18                options: ptr::null_mut(),
19                ignoreUnrecognized: false,
20            },
21        }
22    }
23}
24
25#[repr(transparent)]
26#[derive(Debug, Clone)]
27pub struct JavaVM(*mut sys::JavaVM);
28
29unsafe impl Send for JavaVM {}
30unsafe impl Sync for JavaVM {}
31
32impl JavaVM {
33    pub fn new(libjvm: PathBuf, args: JavaVMInitArgs) -> anyhow::Result<JavaVM> {
34        unsafe fn call(
35            args: JavaVMInitArgs,
36            f: unsafe extern "system" fn(
37                pvm: *mut *mut sys::JavaVM,
38                penv: *mut *mut sys::JNIEnv,
39                args: *mut sys::JavaVMInitArgs,
40            ) -> sys::jint,
41        ) -> anyhow::Result<JavaVM> {
42            let mut vm: *mut sys::JavaVM = ptr::null_mut();
43            let mut env: *mut sys::JNIEnv = ptr::null_mut();
44            let args = &args.args as *const _ as _;
45
46            // call JNI_CreateJavaVM
47            jni_error_code_to_result(f(&mut vm, &mut env, args))?;
48
49            // TODO(tisonkun): null check
50            let java_vm = Ok(JavaVM(vm));
51
52            // TODO(tisonkun): check return value or comment why unchecked
53            ((*(*vm)).DetachCurrentThread)(vm);
54
55            java_vm
56        }
57
58        unsafe {
59            let libjvm = libloading::Library::new(libjvm)?;
60            let f = libjvm.get(b"JNI_CreateJavaVM\0")?;
61            call(args, *f)
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use crate::find_jvm_lib;
70
71    #[test]
72    fn test_create_java_vm() {
73        let jvm_lib = find_jvm_lib().unwrap();
74        let jvm = JavaVM::new(jvm_lib, JavaVMInitArgs::default()).unwrap();
75        assert!(!jvm.0.is_null());
76    }
77}