我正在做一个涉及 Rust 和 Java 的项目。我需要能够从 Rust 端使用 JNI,而无需 Java 端调用它(因为它不是我的代码)。到目前为止,我已经能够确保我的 DLL 被注入(在按键时打开一个小窗口,我一直在使用它进行调试)。
相关代码的简短示例如下:
use jni::sys::{JNI_GetCreatedJavaVMs, JNIInvokeInterface_};
let jvm_ptr = null_mut() as *mut *mut *const JNIInvokeInterface_;
let count = null_mut();
// hasn't crashed
JNI_GetCreatedJavaVMs(jvm_ptr, 1, count); // https://docs.rs/jni/latest/jni/sys/fn.JNI_GetCreatedJavaVMs.html
// crashes
我的问题是:在这种情况下是否可以/如何获得 JNI 环境?
您不能将空指针分块到
vmBuf
参数中,然后通过 vmBuf
告诉它 bufLen
指向长度为 1 的数组。翻译上面链接的 C++ 代码,我会做类似的事情
let mut count: jint = 0;
let check = JNI_GetCreatedJavaVMs(null_mut(), 0, &mut count);
assert!(check == JNI_OK);
let mut vms = vec![null_mut(); count as usize];
let check = JNI_GetCreatedJavaVMs(vms.as_mut_ptr(), vms.len() as i32, &mut count);
assert!(check == JNI_OK);
assert!(vms.len() == count as usize);
尽管这可能有点矫枉过正,因为只能有一个虚拟机。不过,检查计数可能是个好主意。
在评论的帮助下,我让崩溃不再发生。诀窍是预先分配一个数组。
let jvm_ptr = Vec::with_capacity(1);
let count = null_mut();
JNI_GetCreatedJavaVMs(jvm_ptr.as_mut_ptr(), 1, count);
我已经使用这个很多年了。可以抛光....
try {
// how many JVMs is there?
JNI_GetCreatedJavaVMs(NULL, 0, &number_of_JVMs);
}
catch (exception e)
{
int x = 0;
}
if (number_of_JVMs > 0)
{
JavaVM** buffer = new JavaVM * [number_of_JVMs];
JNI_GetCreatedJavaVMs(buffer, number_of_JVMs, &number_of_JVMs);
// 2. get the data
jvm_handle = buffer[0];
if (!jvm_handle == 0)
return true;
else return false;
}