在当前进程中获取JavaVM *的所有实例?

时间:2013-04-24 10:00:41

标签: java c++ windows java-native-interface

这仅适用于Windows JNI是否提供任何返回调用进程的JavaVM*实例的API? 考虑以下场景,将C ++ dll注入java.exe进程。现在的问题是,C ++ DLL如何在运行它的进程中找到JavaVM*的当前实例?

据我所知,所有JNI调用API都需要一个JNIEnv对象,只能从JavaVM*获取对象? http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html

获取JavaVM*的传统方式是通过JNI_OnLoad,但由于我不是要编写一个由Java使用的本机库,我认为不会这样做。 http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

1 个答案:

答案 0 :(得分:5)

您可以使用JNI_GetCreatedJavaVMs

jsize nVMs;
JNI_GetCreatedJavaVMs(NULL, 0, &nVMs); // 1. just get the required array length
JavaVM** buffer = new JavaVM*[nVMs];
JNI_GetCreatedJavaVMs(buffer, nVMs, &nVMs); // 2. get the data

此代码是" safe"询问缓冲区有多大的版本,然后再次调用以获取数据。但是,主要的Windows JVM(Hotspot)并不支持每个进程多个JVM,因此仅为一个元素分配缓冲区可能就足够了。 JNI_GetCreatedJavaVMs是调用API的一部分,因此由jvm.dll导出。

  

我没有编写Java使用的本地库

如果您在库中创建JVM,那就是您需要的所有内容,因为您必须加载jvm.dll。我无法帮助你,因为你并没有写出你的图书馆将如何被调用。如果您的库由另一个本机库使用,该库创建JVM或从JVM加载并且由于某种原因它没有将JavaVM*传递给您,您可以尝试这样的事情:

#include <Windows.h>
#include <jni.h>
// ...
typedef jint (JNICALL * GetCreatedJavaVMs)(JavaVM**, jsize, jsize*);
GetCreatedJavaVMs jni_GetCreatedJavaVMs;
// ...
jni_GetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(GetModuleHandle(
        TEXT("jvm.dll")), "JNI_GetCreatedJavaVMs");