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

Get all instance of JavaVM* in the current process?

本文关键字:JavaVM 实例 进程 获取      更新时间:2023-10-16

这只针对Windows。
JNI是否提供任何API来返回调用进程的JavaVM*的所有实例?
考虑以下场景,一个c++ dll被注入到java.exe进程中。现在的问题是,c++ dll如何在它运行的进程中找到JavaVM*的当前实例?

据我所知,所有JNI调用API都需要一个只能从JavaVM*获得的JNIEnv对象,对吗?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

您可以使用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");