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

4
这只适用于Windows。
JNI是否提供任何API以返回调用进程的所有JavaVM*实例?
考虑以下情况,一个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个回答

7

你可以使用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

这段代码是“安全”的版本,它会询问缓冲区的大小,然后再调用第二次以获取数据。但是,主要的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");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接