c++;插件->;JNI-->;Java类路径

c++;插件->;JNI-->;Java类路径,java,c++,plugins,java-native-interface,Java,C++,Plugins,Java Native Interface,我正在尝试为应用程序创建一个插件。插件需要用C++编写。我想在Windows和Mac上使用这个插件,所以用Java编写这个插件会很好 我的问题是,还有一个使用Java的插件。因为它们使用的是同一个主应用程序,所以已经有一个正在运行的JavaVM JavaVM *jvm = NULL; jsize jvm_count = 0; jint res=0; res = JNI_GetCreatedJavaVMs (&jvm, 1, &jvm_count); 我的问题: 如何更改/修

我正在尝试为应用程序创建一个插件。插件需要用C++编写。我想在Windows和Mac上使用这个插件,所以用Java编写这个插件会很好

我的问题是,还有一个使用Java的插件。因为它们使用的是同一个主应用程序,所以已经有一个正在运行的JavaVM

JavaVM *jvm = NULL;
jsize jvm_count = 0;
jint res=0;


res = JNI_GetCreatedJavaVMs (&jvm, 1, &jvm_count);
我的问题: 如何更改/修改现有JavaVM的类路径?或者如何创建新的/第二个JavaVM

我尝试通过JNI加载我的jar文件:

/* URL CLASS */
jclass URLcls;
URLcls = env->FindClass("java/net/URL");

/* URL CLASS CONSTRUCTOR*/
jmethodID URLclsMid;
URLclsMid = env->GetMethodID(URLcls, "<init>","(Ljava/lang/String;)V");

/* URL OBJECT */
jobject URLobj;
jstr = env->NewStringUTF("file:/path/to/test/file/test.jar");
URLobj = env->NewObject(URLcls, URLclsMid, jstr);

/* URL Array */
jobjectArray URLArray;
URLArray = env->NewObjectArray(1, URLcls, URLobj);



/*Thread Class*/
jclass ThreadCLS;
ThreadCLS = env->FindClass("java/lang/Thread");

/*Static Method currentThread*/
jmethodID ThreadCLS_currentThread;
ThreadCLS_currentThread = env->GetStaticMethodID(ThreadCLS, "currentThread","()Ljava/lang/Thread;");

/*get current Thread Object*/
jobject currentThread;
currentThread = env->CallStaticObjectMethod(ThreadCLS, ThreadCLS_currentThread);

/* getContextClassLoader method */  
jmethodID currentThread_getContextClassLoader;
currentThread_getContextClassLoader = env->GetMethodID(ThreadCLS, "getContextClassLoader","()Ljava/lang/ClassLoader;");

/* ClassLoader Class */     
jclass ClassLoaderCLS;
ClassLoaderCLS = env->FindClass("java/lang/ClassLoader");

/* get ClassLoader Object */
jobject classLoader = env->CallObjectMethod(currentThread, currentThread_getContextClassLoader);


/* URLClassLoader Class */
jclass URLClassLoaderCLS;
URLClassLoaderCLS = env->FindClass("java/net/URLClassLoader");

/* Static Method newInstance */
jmethodID URLClassLoaderCLS_newInstance;
URLClassLoaderCLS_newInstance = env->GetStaticMethodID(URLClassLoaderCLS, "newInstance","([Ljava/net/URL;Ljava/lang/ClassLoader;)Ljava/net/URLClassLoader;");


/* get new URLClassLoader Instance */
jobject myURLClassLoaderInstance;
myURLClassLoaderInstance = env->CallStaticObjectMethod(URLClassLoaderCLS, URLClassLoaderCLS_newInstance, URLArray, classLoader);


/* get setContextClassLoader Method */
jmethodID currentThread_setContextClassLoader;
currentThread_setContextClassLoader = env->GetMethodID(ThreadCLS, "setContextClassLoader","(Ljava/lang/ClassLoader;)V");

/* trying to set the ClassLoader from the current Thread */    
env->CallVoidMethod(currentThread, currentThread_setContextClassLoader, myURLClassLoaderInstance);


/* get loadClass Method */
jmethodID loadClass;
loadClass = env->GetMethodID(URLClassLoaderCLS, "loadClass","(Ljava/lang/String;)Ljava/lang/Class;");


/* get a Class from my test.jar*/
jstring methodString = env->NewStringUTF("de.domain.sayHello");
jclass myClass = (jclass)env->CallObjectMethod(myURLClassLoaderInstance, loadClass, methodString);


/*working till here*/


jmethodID myClassMethod;
myClassMethod = env->GetMethodID(myClass, "doIt","()Ljava/lang/String;");

if (myClassMethod == NULL) {
    // Method of Class "de.domain.sayHello" not found
}
/*URL类*/
jclass URLcls;
URLcls=env->FindClass(“java/net/URL”);
/*URL类构造函数*/
jMethod URLclsMid;
URLclsMid=env->GetMethodID(URLcls,“,”(Ljava/lang/String;)V);
/*URL对象*/
jobject URLobj;
jstr=env->NewStringUTF(“文件:/path/to/test/file/test.jar”);
URLobj=env->NewObject(URLcls、URLclsMid、jstr);
/*URL数组*/
jobjectArray-URLArray;
URLArray=env->NewObjectArray(1,URLcls,URLobj);
/*螺纹类*/
jclass-ThreadCLS;
ThreadCLS=env->FindClass(“java/lang/Thread”);
/*静态方法currentThread*/
jmethodID ThreadCLS_currentThread;
ThreadCLS_currentThread=env->GetStaticMethodID(ThreadCLS,“currentThread”,“()Ljava/lang/Thread;”;
/*获取当前线程对象*/
作业对象当前线程;
currentThread=env->CallStaticObjectMethod(ThreadCLS,ThreadCLS\u currentThread);
/*getContextClassLoader方法*/
jmethodID currentThread_getContextClassLoader;
currentThread_getContextClassLoader=env->GetMethodID(ThreadCLS,“getContextClassLoader”,“()Ljava/lang/ClassLoader;”;
/*类加载器类*/
jclass类装入器;
ClassLoaderCLS=env->FindClass(“java/lang/ClassLoader”);
/*获取类加载器对象*/
jobject classLoader=env->CallObjectMethod(currentThread,currentThread\u getContextClassLoader);
/*URLClassLoader类*/
jclass URLClasseLoaderCLS;
URLClassLoaderCLS=env->FindClass(“java/net/URLClassLoader”);
/*静态方法newInstance*/
jmethodID URLClasseLoaderCLS_newInstance;
URLClassLoaderCLS_newInstance=env->GetStaticMethodID(URLClassLoaderCLS,“newInstance”,“([Ljava/net/URL;Ljava/lang/ClassLoader;)Ljava/net/URLClassLoader;”;
/*获取新的URLClassLoader实例*/
jobject myURLClassLoaderInstance;
myURLClassLoaderInstance=env->CallStaticObjectMethod(URLClassLoaderCLS,URLClassLoaderCLS\u newInstance,URLArray,classLoader);
/*获取setContextClassLoader方法*/
jmethodID currentThread_setContextClassLoader;
currentThread_setContextClassLoader=env->GetMethodID(ThreadCLS,“setContextClassLoader”,“(Ljava/lang/ClassLoader;)V”);
/*正在尝试从当前线程设置类加载器*/
env->CallVoidMethod(currentThread,currentThread_setContextClassLoader,myURLClassLoaderInstance);
/*获取loadClass方法*/
jmethodideloadclass;
loadClass=env->GetMethodID(URLClassLoaderCLS,“loadClass”,“(Ljava/lang/String;)Ljava/lang/Class;”;
/*从test.jar获取一个类*/
jstring methodString=env->NewStringUTF(“de.domain.sayHello”);
jclass myClass=(jclass)env->CallObjectMethod(myURLClassLoaderInstance,loadClass,methodString);
/*一直工作到这里*/
jmethodidmyclassmethod;
myClassMethod=env->GetMethodID(myClass,“doIt”,“()Ljava/lang/String;”);
if(myClassMethod==NULL){
//未找到类“de.domain.sayHello”的方法
}
我可以做什么来更改类路径?或者加载我的jar文件

谢谢
Lisa

我已经解决了我的问题。我没有设法设置或影响类路径,以便我可以使用:

jmethodID myClassMethod;
myClassMethod = env->GetMethodID(myClass, "doIt","()Ljava/lang/String;");

if (myClassMethod == NULL) { 
    // Method of Class "de.domain.sayHello" not found
}
相反,我使用Java反射创建了类的一个对象

查找我的Java类:(在问题代码中的“/工作到这里/”之后)

从我的Java类中获取对象:

/* CLASS newInstance Method*/
jmethodID ClassNewInstanceMid = env->GetMethodID(Classcls, "newInstance","()Ljava/lang/Object;");



jobject myObject = env->CallObjectMethod(myJavaClass, ClassNewInstanceMid);
这样,我从Java类中获得了一个对象(调用了默认构造函数)

通过jobject,我可以通过java反射调用对象的一个方法

在Java端,我加载了应用程序:

import java.io.File;

public class sayHello {

public static native void sayHi(String message, int times);

public sayHello()
{
    System.out.println("object created :) ");

}

public void doIt(String test)
{


     File myfile = new File(test);

       if(myfile.exists())
           System.load(myfile.getAbsolutePath());
       else
           System.out.println("Something went wrong :( ");


       sayHi("C++ Funktion Call out of Java",5);
}

}
在我的C++插件中,我实现了这个函数:

JNIEXPORT void JNICALL Java_de_domain_sayHello_sayHi
(JNIEnv *localEnv, jclass clazz, jstring message, jint times)
{

    int myT = times;

    for(int i=0;i<myT;i++)
        fprintf(stderr,"%s\n", localEnv->GetStringUTFChars(message, NULL));

}
在这个函数中,使用函数中的JNIEnv“localEnv”还是“env”(全局变量)并不重要

谢谢
Lisa

我认为您无法以可靠的方式修改正在运行的vm的类路径。您可以尝试实现自定义类加载器,也可以尝试使用调用API启动新vm,请参阅:JNI_CreateJavaVM()。更多信息:@Alex Barker感谢您的评论。据我所知,当主应用程序的一个其他线程中已经有正在运行的VM时,不可能创建新VM。
JNIEXPORT void JNICALL Java_de_domain_sayHello_sayHi
(JNIEnv *localEnv, jclass clazz, jstring message, jint times)
{

    int myT = times;

    for(int i=0;i<myT;i++)
        fprintf(stderr,"%s\n", localEnv->GetStringUTFChars(message, NULL));

}
jclass myCLS = env->FindClass("de/domain/sayHello");
if(myCLS != NULL){
     //class found
}