这仅适用于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
答案 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");