gpt4 book ai didi

java - 在 C++ 中使用 JNI 创建 JVM 不返回

转载 作者:太空狗 更新时间:2023-10-29 21:48:10 25 4
gpt4 key购买 nike

我正在尝试为我的服务器 java 程序启动 jvm。服务器 java 程序在内部启动另一个 java 进程,我正在调用的类/方法具有 system.exist(0)我的程序运行良好,它启动了所需的 java 进程,但程序控制不会回到 c++。它只是存在,即父进程死亡。这是我的完整代码。

    #include <stdexcept>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <include/jni.h>

#include <string>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <signal.h>


class JVMLauncherException : public std::runtime_error {
public:
JVMLauncherException(const std::string& message) : std::runtime_error(message)
{
};
};

class Server_JVMLauncher {
public:
Server_JVMLauncher();
void addJars(std::string inJar);
void LaunchJVM();
void StartServer_Server();
void AddServerArguments(std::string);
void StopServer_Server();
private:
typedef jint (JNICALL *CreateJavaVM)(JavaVM **pvm, void **penv, void *args);

HINSTANCE m_hDllInstance;

std::string m_JavaHome;
std::string m_ProductLibDir;
std::string m_JvmDllLocation;

CreateJavaVM m_JVMInstance;
jclass m_CacheServerLauncherClass;
jmethodID m_MainMethodID;
JNIEnv *m_JVMEnv;
JavaVM *m_RunningJVMInstance;

std::vector<std::string> m_listOfJars;
std::vector<std::string> m_ServerArguments;

void CheckForJNIException();
protected:
};

Server_JVMLauncher::Server_JVMLauncher() {
// Check for JAVA_HOME
char *pValue;
size_t len;
errno_t err = _dupenv_s( &pValue, &len, "JAVA_HOME" );
if ( err ) {
throw JVMLauncherException("JAVA_HOME not defined");
}
m_JavaHome = pValue;
m_JvmDllLocation = m_JavaHome + "\\jre\\bin\\client\\jvm.dll";

err = _dupenv_s( &pValue, &len, "Server_" );
if ( err ) {
throw JVMLauncherException("Server_ not defined");
}
m_ProductLibDir = pValue;

m_listOfJars.push_back("dep1.jar");
m_listOfJars.push_back("dep2.jar");
m_listOfJars.push_back("dep3.jar");
m_listOfJars.push_back("dep4.jar");
m_listOfJars.push_back("dep5.jar");
}
void Server_JVMLauncher::AddServerArguments(std::string inParam) {
m_ServerArguments.push_back(inParam);
}
void Server_JVMLauncher::LaunchJVM() {
// Construct the product specific class path.
std::string strJavaClassPath = "-Djava.class.path=";
for ( std::size_t idx = 0; idx < m_listOfJars.size() - 1 ; idx++) {
strJavaClassPath += m_ProductLibDir + "\\lib\\" + m_listOfJars[idx] + ";";
}
strJavaClassPath += m_ProductLibDir + "\\lib\\" + m_listOfJars[m_listOfJars.size() - 1] ;

// consruct java.library.path
std::string strJavaLibraryPath = "-Djava.library.path=";
strJavaLibraryPath += m_JavaHome + "\\lib" + "," + m_JavaHome + "\\jre\\lib";


// try loading jvm dll
m_hDllInstance = LoadLibraryA(m_JvmDllLocation.c_str());
if( m_hDllInstance == 0) {
throw JVMLauncherException("Cannot load jvm.dll");
}
m_JVMInstance = (CreateJavaVM)GetProcAddress(m_hDllInstance, "JNI_CreateJavaVM");
if ( m_JVMInstance == NULL ) {
throw JVMLauncherException("Cannot load jvm.dll");
}

JavaVMOption options[2];
options[0].optionString = const_cast<char*>(strJavaClassPath.c_str());
options[1].optionString = const_cast<char*>(strJavaLibraryPath.c_str());

JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_6; //JNI Version 1.4 and above
vm_args.options = options;
vm_args.nOptions = 2;
vm_args.ignoreUnrecognized = JNI_TRUE;

//Create the JVM

jint res = m_JVMInstance(&m_RunningJVMInstance, (void **)&m_JVMEnv, &vm_args);
if (res < 0) {
throw JVMLauncherException("Could not launch the JVM");
}
//m_RunningJVMInstance->AttachCurrentThread((void **)&m_JVMEnv, &vm_args);

m_CacheServerLauncherClass = m_JVMEnv->FindClass("com/Server/internal/ServerLauncher");
CheckForJNIException();

m_MainMethodID = m_JVMEnv->GetStaticMethodID(m_CacheServerLauncherClass, "main", "([Ljava/lang/String;)V");
CheckForJNIException();
}

void Server_JVMLauncher::StartServer_Server() {

if ( m_RunningJVMInstance->AttachCurrentThread((LPVOID *)&m_JVMEnv, NULL) ) {
std::cout << "Fail to attach the current thread " << std::endl;
}

jclass StringClass = m_JVMEnv->FindClass("java/lang/String");
int numOfArguments = (int)m_ServerArguments.size() + 2 ;
int argumentIndex = 0;

jobjectArray jargs = m_JVMEnv->NewObjectArray(numOfArguments, StringClass, NULL);

m_JVMEnv->SetObjectArrayElement(jargs, argumentIndex++, m_JVMEnv->NewStringUTF("start"));

std::string strJavaClassPath = "-classpath=";
strJavaClassPath += "\"";
for ( std::size_t idx = 0; idx < m_listOfJars.size() - 1 ; idx++) {
strJavaClassPath += m_ProductLibDir + "\\lib\\" + m_listOfJars[idx] + ";";
}
strJavaClassPath += m_ProductLibDir + "\\lib\\" + m_listOfJars[m_listOfJars.size() - 1] ;
strJavaClassPath += "\"";

m_JVMEnv->SetObjectArrayElement(jargs, argumentIndex++, m_JVMEnv->NewStringUTF(strJavaClassPath.c_str()));

for ( std::vector<std::string>::iterator iter = m_ServerArguments.begin(); iter != m_ServerArguments.end(); ++iter) {
std::string argument = *iter;
m_JVMEnv->SetObjectArrayElement(jargs, argumentIndex++, m_JVMEnv->NewStringUTF(argument.c_str()));
}

m_JVMEnv->CallStaticVoidMethod(m_CacheServerLauncherClass, m_MainMethodID, jargs);

m_RunningJVMInstance->DestroyJavaVM();

std::cout << "I am done with launching java program" << std::endl;
CheckForJNIException();
}
void Server_JVMLauncher::StopServer_Server() {
jclass StringClass = m_JVMEnv->FindClass("java/lang/String");
int numOfArguments = 2 ;

jobjectArray jargs = m_JVMEnv->NewObjectArray(numOfArguments, StringClass, NULL);

m_JVMEnv->SetObjectArrayElement(jargs, 0, m_JVMEnv->NewStringUTF("stop"));
m_JVMEnv->SetObjectArrayElement(jargs, 1, m_JVMEnv->NewStringUTF("-dir=E:\\Avinash\\personal\\work\\CreateJvm\\Debug\\gfecs"));

m_JVMEnv->CallStaticVoidMethod(m_CacheServerLauncherClass, m_MainMethodID, jargs);
CheckForJNIException();

}
void Server_JVMLauncher::CheckForJNIException() {
jthrowable expt = m_JVMEnv->ExceptionOccurred();
if (expt != NULL) {
m_JVMEnv->ExceptionClear();
jmethodID toString = m_JVMEnv->GetMethodID(m_JVMEnv->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
jstring estring = (jstring) m_JVMEnv->CallObjectMethod(expt, toString);
jboolean isCopy;
std::string message = m_JVMEnv->GetStringUTFChars(estring, &isCopy);
throw JVMLauncherException(message);
}
}

int main( int argc, char **argv) {
try {
Server_JVMLauncher instanceServer_;
instanceServer_.LaunchJVM();
instanceServer_.StartServer_Server();
} catch (JVMLauncherException &excp ) {
std::cout << excp.what() << std::endl;
}
return 0;
}

最佳答案

当你调用 CallStaticVoidMethod() 时,它不会创建子进程,而是在调用线程中运行 Java main() 方法,阻塞调用者直到它完成。如果 Java 程序调用 System.exit() 进程将立即退出并且不会返回给调用者:不要调用 System.exit()

关于java - 在 C++ 中使用 JNI 创建 JVM 不返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11401616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com