2015-10-14 90 views
0

我需要從C++應用程序調用java方法。我已按照這些教程中的說明進行操作:http://hildstrom.com/projects/jni/index.htmlhttp://www.codeproject.com/Articles/22881/How-to-Call-Java-Functions-from-C-Using-JNI。這裏是我的代碼:使用JNI在C++中調用java方法

#include <stdio.h> 
#include "../Header/jni.h" 

JNIEnv* create_vm(JavaVM **jvm) 
{ 
    JNIEnv* env; 
    JavaVMInitArgs args; 
    JavaVMOption options; 
    args.version = JNI_VERSION_1_6; 
    args.nOptions = 1; 
    options.optionString = "-Djava.class.path= C:\\Users\\vhsn\\workspace-SP\\helloWorld\\src\\helloWorld"; 
    args.options = &options; 
    args.ignoreUnrecognized = 0; 
    int rv; 
    rv = JNI_CreateJavaVM(jvm, (void**)&env, &args); 
    if (rv < 0 || !env) 
     printf("Unable to Launch JVM %d\n",rv); 
    else 
     printf("Launched JVM! :)\n"); 
    return env; 
} 

void invoke_class(JNIEnv* env) 
{ 
    jclass hello_world_class; 
    jmethodID main_method; 
    jmethodID square_method; 
    jmethodID power_method; 
    jint number=20; 
    jint exponent=3; 
    hello_world_class = env->FindClass("HelloWorld"); 
    main_method = env->GetStaticMethodID(hello_world_class, "main", "([Ljava/lang/String;)V"); 
    square_method = env->GetStaticMethodID(hello_world_class, "square", "(I)I"); 
    power_method = env->GetStaticMethodID(hello_world_class, "power", "(II)I"); 
    printf("carregou metodos"); 
    env->CallStaticVoidMethod(hello_world_class, main_method, NULL); 
    printf("%d squared is %d\n", number, 
     env->CallStaticIntMethod(hello_world_class, square_method, number)); 
    printf("%d raised to the %d power is %d\n", number, exponent, 
     env->CallStaticIntMethod(hello_world_class, power_method, number, exponent)); 
} 

int main(int argc, char **argv) 
{ 
    JavaVM *jvm; 
    JNIEnv *env; 
    env = create_vm(&jvm); 
    if(env == NULL) 
     return 1; 
    invoke_class(env); 
    return 0; 
} 

林使用MinGW compilling它,與位於jvm.lib鏈接 「C:\ Program Files文件(x86)的\的Java \ jdk1.7.0_79 \ lib中」。

它編譯成功,但是當我執行它只打印「啓動JVM!:)」,然後崩潰。 當我嘗試調試時,它在第一個GetStaticMethodID調用中崩潰。我認爲它沒有正確加載HelloWorld.class,但我不知道爲什麼。

有沒有人遇到類似的問題或有什麼問題可能是什麼想法?

我在一臺Windows機器64位,我使用java 32位,因爲它沒有編譯與Java 64位jvm.lib。

編輯:

我添加了一個

if(env->ExceptionOccurred()){ 
      env->ExceptionDescribe(); 
     } 

,它拋出一個java.lang.NoClassDefFoundError。我認爲我不清楚要投入什麼

options.optionString = "-Djava.class.path=C:\\Users\\vhsn\\workspace\\AAPlugin\\Debug"; 

它是.class文件還是.jar文件的路徑?

非常感謝!

+0

如果您還發布了「HelloWorld」java類的代碼,那將會很好。 – Brick

+0

我認爲這裏沒有足夠的信息來回答你的問題。可能是你在'FindClass'中指定'HelloWorld'的路徑,但我們不知道它所在的包。可能是因爲它找不到類文件,可能是因爲Java類沒有有你指定的方法......在任何情況下,你應該在基本上所有對JNI的調用(尤其是如果你知道你正在崩潰)之後檢查異常。在'FindClass'處拋出的異常不會導致你崩潰,除非你先完成* next * JNI調用而沒有清除JVM上的異常。 – Brick

回答

0

我建議找不到類HelloWorldhello_world_class = env->FindClass("HelloWorld")調用返回null,所以hello_world_class`爲null,所以使用它的下一次調用會崩潰。

您需要檢查每個JNI調用的結果,無一例外。你可以假設沒有任何與JNI。

+0

嗨!感謝您的回答,我現在正在檢查hello_world_class並拋出一個異常:if(env-> ExceptionOccurred()){ExceptionThreade();}} \t \t}它拋出java.lang.NoClassDefFoundError。但是我在.exe的相同位置有HelloWorld.class和HelloWorld.jar。 –

0

好的,我明白了。

我不得不做兩個變化:

首先我設定的路徑.jar文件,包括它的名字:在的findClass方法

char * classPath = (char *) "-Djava.class.path=HelloWorld.jar"; 

其次,我必須指定其包名:

hello_world_class = env->FindClass("helloWorld/HelloWorld"); 

非常感謝您的回答。