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 jni_error_code_to_result(f(&mut vm, &mut env, args))?;
48
49 let java_vm = Ok(JavaVM(vm));
51
52 ((*(*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}