c ++插件 - > JNI - > Java Classpath [英] c++ Plugin -> JNI --> Java Classpath

查看:214
本文介绍了c ++插件 - > JNI - > Java Classpath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i am trying to create a Plugin for an Application. The Plugin needs to be written in c++. I want to use the Plugin on Windows and on Mac, so it would be great to write the Plugin in Java.

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

My Problem, there is an other Plugin using Java. Since they are using the same main Application there is already an running JavaVM.

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


res = JNI_GetCreatedJavaVMs (&jvm, 1, &jvm_count);

我的问题:
如何更改/修改现有JavaVM的类路径?或者我如何创建新的/第二个JavaVM?

My Problem: How can i change / modify the Classpath of the existing JavaVM? Or how can i create a new / second JavaVM?

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

I've tryed to load my jar file via JNI:

/* 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
}

如何更改Classpath?或加载我的jar文件?

What can i do to change the Classpath? or to load my jar File?

谢谢
Lisa

Thanks Lisa

推荐答案

我已经解决了我的问题。我没有设法或影响Classpath以便我可以使用:

I've solved my Problem. I did not manage to set or influence the Classpath in a way so that i can use:

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

if (myClassMethod == NULL) { 
    // Method of Class "de.domain.sayHello" not found
}

而不是我用Java反射创建了我的类的对象。

Instead of this i've created an Object of my Class using Java Reflection.

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

Find my Java Class: (after "/working till here/" from the code of my question)

/* Class CLASS */
jclass Classcls = env->FindClass("java/lang/Class");


/* String CLASS */
jclass StringCls = env->FindClass("java/lang/String");

jstring methodString = env->NewStringUTF("de.domain.sayHello");

jclass myJavaClass = (jclass)env->CallObjectMethod(MyURLClassLoaderInstance, URLClassLoaderCLS_loadClass, methodString);

从我的Java类中获取一个对象:

Get an Object from my Java Class:

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



jobject myObject = env->CallObjectMethod(myJavaClass, ClassNewInstanceMid);

我从我的Java类中得到了一个对象。 (默认构造函数被调用)

with this i got an object from my Java Class. (The Default Constructor was called)

使用jobject我可以通过java反射调用我的对象的方法。我将带有应用程序路径的Sring传递给我的Java方法。

With the jobject i was able to call a method of my object via java reflection. I passed a Sring with the Application path to my Java Method.

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

On the Java side i loaded the Application:

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 ++插件中我实现了这个函数:

In my c++ Plugin i implemented this function:

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));

}

一个有趣的事情:
在JNICALL方法(Java_de_domain_sayHello_sayHi)里面,我能够通过JNI找到我的电话:

An Interessting thing: Inside the JNICALL Method (Java_de_domain_sayHello_sayHi) i am able to find my Call via JNI:

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

在这个函数中,无论我是否使用函数o中的JNIEnvlocalEnv都没关系renv(全局变量)

Inside this function it dosen't matter whether i use the JNIEnv "localEnv" from the function or "env" (global variable)

谢谢
Lisa

Thanks Lisa

这篇关于c ++插件 - &gt; JNI - &gt; Java Classpath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆