jni java jar c,你可以在使用JNI从java调用的c ++函数中创建一个新的JVM吗?

So my setup is that I have a .dll which is developed by me (A.dll) which in the original application is called from an external process which is basically just a .exe file that I do not have the source code for (B.exe). The purpose of A.dll is to communicate with a .jar file, which is also developed by me (C.jar). So in the application, the "communication flows" as shown below

B.exe -> A.dll -> (through JNI) -> C.jar

Now, what i want to do is to add the calls going between A.dll and C.jar as a part of my test suite in the development environment for C.jar. What I have so far is that I have created another .dll (D.dll) which mirrors all functions in A.dll, but with JNIEXPORT, and simply makes direct call to the respective function in A.dll. So the "communication flow" in this situation will be as follows:

Unit test in C.jar development framework -> (through JNI) -> D.dll -> A.dll -> (through JNI) -> C.jar

At this point, a very simple function call that simply prints out something in C.jar works through the whole chain; all the way from the unit test call and into C.jar. The problem however arises when i call the function in A.dll which creates a new JVM using CreateJavaVM(), which produces the following error:

Error occurred during initialization of VM

Unable to load native library: The specified procedure could not be found

So basically I'm wondering if it is actually possible to do this, or is it just simply impossible to call CreateJavaVM() when there is already a running JVM in the same process? I know that you can't call CreateJavaVM() several times within the same process, but in this situation it is only called once but a JVM already exists in the process - can you even have several JVMs running in the same process?

SOLUTION:

Thanks to @apangin's answer the code snippet below solved my problem:

jsize nVMs = 0;

JavaVM** buffer;

jni_GetCreatedJavaVMs = (GetCreatedJavaVMs) GetProcAddress(GetModuleHandle(

TEXT("jvm.dll")), "JNI_GetCreatedJavaVMs");

if (jni_GetCreatedJavaVMs == NULL) {

// stuff

CreateJavaVM(&jvm, (void **) &env, &args);

} else {

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

buffer[0]->GetEnv((void **) &env, jni_version); // 3. get environment

jvm = buffer[0];

}

解决方案

Current JNI specification explicitly states that HotSpot source code.

Even if your dll calls JNI_CreateJavaVM only once, it does not mean that this is the very first call within the whole process. In fact, JNI_CreateJavaVM is first called by java.exe or by another launcher of your IDE (idea.exe, eclipse.exe, netbeans.exe etc).

Therefore, instead of creating Java VM blindly, A.dll should check first if JVM already exists in current process by calling JNI_GetCreatedJavaVMs. If the function returns nonempty array, then use GetEnv or AttachCurrentThread to obtain JNIEnv* for the existing VM, otherwise create a new VM.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值