3

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

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

传统的获取方式JavaVM*是 via,JNI_OnLoad但由于我没有编写 Java 使用的本机库,我认为这不会奏效。 http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

4

1 回答 1

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

此代码是“安全”版本,它询问缓冲区必须有多大,然后再次调用以获取数据。但是,主要的 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");
于 2013-04-27T16:56:40.143 回答