How do I get a JavaVM or JNIEnv from an already-running JVM using JNI?

901 views Asked by At

I am working on a project which involves Rust and Java. I need to be able to use the JNI from the Rust side, without the Java side calling invoking it (because it is not my code). So far, I have been able to ensure my DLL is injected (open a small window on keypress, I have been using this for debugging).

A shortened example of the relevant code is the following:

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

My question is this: is it possible to/how do I get a JNI environment in this situation?

3

There are 3 answers

0
majorsopa On BEST ANSWER

With the help of the comments, I got that crash to stop happening. The trick was to pre-allocate an array.

let jvm_ptr = Vec::with_capacity(1).as_mut_ptr();
let count = null_mut();

JNI_GetCreatedJavaVMs(jvm_ptr, 1, count);
0
Caesar On

You can't chunk a null pointer into the vmBuf parameter and then tell it that vmBuf points to an array of length 1 via bufLen. Translating the C++ code linked above, I would do something like

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);

though that's probably a bit overkill since there can only be one VM. Still, checking the count is probably a good idea.

0
Tonecops On

I have been using this many years. It can be polished....

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;
 }