簡體   English   中英

您可以使用JNI在從Java調用的c ++函數中創建新的JVM嗎?

[英]Can you create a new JVM in a c++ function called from java using JNI?

因此,我的設置是我有一個由我開發的.dll( A.dll ),該文件在原始應用程序中是從外部進程中調用的,該進程基本上只是一個.exe文件,而我沒有( B .exe )。 A.dll的目的是與.jar文件進行通訊,該文件也是由我開發的( C.jar )。 因此在應用程序中,“通信流”如下所示

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

現在,我想做的是將A.dllC.jar之間的調用添加為C.jar開發環境中測試套件的一部分。 到目前為止,我已經創建了另一個.dll( D.dll ),它鏡像了A.dll中的所有功能,但是使用JNIEXPORT,並且直接對A.dll中的各個功能進行了直接調用。 因此,這種情況下的“通信流程”如下:

C.jar開發框架中的單元測試 ->(通過JNI)-> D.dll- > A.dll ->(通過JNI)-> C.jar

在這一點上,一個非常簡單的函數調用可以簡單地打印出C.jar中的某些內容, 貫穿整個鏈。 從單元測試調用一直到C.jar 但是,當我在A.dll中調用函數時會出現問題,該函數使用CreateJavaVM()創建新的JVM,並產生以下錯誤:

VM初始化期間發生錯誤無法加載本機庫:找不到指定的過程

因此,基本上,我想知道是否確實可以執行此操作,或者在同一進程中已經有運行中的JVM時調用CreateJavaVM()根本就不可能嗎? 我知道您不能在同一進程中多次調用CreateJavaVM() ,但是在這種情況下,它只能被調用一次,但是該進程中已經存在一個JVM-您甚至可以在同一進程中運行多個JVM嗎?

解:

感謝@apangin的回答,下面的代碼片段解決了我的問題:

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];
}

當前的JNI規范明確聲明不支持在單個進程創建多個VM ,並且實際上是在HotSpot源代碼中聲明的

即使您的dll僅調用一次JNI_CreateJavaVM ,也並不意味着這是整個過程中的第一個調用。 實際上, JNI_CreateJavaVM首先由java.exe或IDE的另一個啟動程序( idea.exeeclipse.exenetbeans.exe等) idea.exe

因此,而不是盲目地創建Java VM, A.dll應該通過調用JNI_GetCreatedJavaVMs首先檢查JVM是否在當前進程中已經存在。 如果函數返回非空數組,則使用GetEnvAttachCurrentThread為現有VM獲取JNIEnv* ,否則創建一個新VM。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM