2014-02-08 101 views
0

我有一個非常直接的代碼來通過JNI從C++調用JAVA函數,但它只適用於我提供編譯的.class文件和捆綁的.jar文件。如果我刪除其中的任何一個,我的應用程序將停止工作示例代碼:JNI C++爲什麼我還需要.class和.jar?

void JniProvider::CreateVM(const QString compiledSource, const QString jar) throw(std::runtime_error) { 
    QString  classpath = QString("-Djava.class.path=%1;%2").arg(compiledSource).arg(jar); 
    QByteArray cpbytes  = classpath.toLocal8Bit(); 
    char*  chrpath  = cpbytes.data(); 
    // VM Arguments size: 
    const int optionsSize = 2; 
    // jvm options: 
    JavaVMOption options[optionsSize]; 
       options[0].optionString = "-Djava.compiler=NONE"; 
       options[1].optionString = chrpath; 
    // jvm args 
    JavaVMInitArgs vm_args; 
        vm_args.version    = JNI_VERSION_1_6; 
        vm_args.nOptions   = optionsSize; 
        vm_args.options    = options; 
        vm_args.ignoreUnrecognized = JNI_TRUE; 
    // startup jvm 
    jint responseCode = JNI_CreateJavaVM(&virtualMachine, reinterpret_cast<void**>(&environment), &vm_args); 
    if (responseCode < 0) { 
     virtualMachine->DestroyJavaVM(); 
     throw std::runtime_error("Failed to create Java virtual machine."); 
    } 
} 

注意classpath行。如果我刪除jar,我無法通過jni調用任何函數。當我再次設置它一切正常。它的功能是否需要編譯源代碼和bunbled jar(也包含依賴jar)呢?

@編輯: 感謝您的回覆。請允許我在一個地方澄清一些彈出的問題。因此,Java項目具有內的Netbeans 7.4的結構如下:

Core 
Source Packages 
    core 
    Core.java 
    model 
    model.java 
Test Packages 
Libraries 
    enttoolkit.jar 
    mail.jar 
    wm-isclient.jar 

正如你可以看到我有三個依賴外部jar文件。無論我是否喜歡它,Java應用程序都會使用這些。編譯後,以下結構將出現在項目的dist文件夾:

lib 
enttoolkit.jar 
mail.jar 
wm-isclient.jar 
Core.jar 
core 
    core.class 
META-INF 
    MANIFEST.MF 
model 
    model.class 

我有core.jar添加里面編譯的類,並在它的外部jar文件lib文件夾。

現在到了實際有問題的部分。如果我稍後在env-> Findclass失敗時從CreateVM函數的類路徑中刪除.class或.jar文件。它只是不會找到任何類,如果我提供類文件和jar文件它會成功,我可以調用任何方法,從靜態或不靜態。

MANIFEST.MF內容:

Manifest-Version: 1.0 
Ant-Version: Apache Ant 1.9.1 
Created-By: 1.7.0_25-b17 (Oracle Corporation) 
Class-Path: lib/enttoolkit.jar lib/mail.jar lib/wm-isclient.jar 
X-COMMENT: Main-Class will be added automatically by build 
Main-Class: core.Core 

@Edit(10:30): 該錯誤是NoClassDefFoundError的。 compiledSource的值是包含類文件本身的.class文件的路徑,而jar與jar文件相同。例如:

"-Djava.class.path=C:/Users/johorvat/AppData/Local/Temp/resource.class" <- The upper NoClassDefFoundError 
"-Djava.class.path=C:/Users/johorvat/AppData/Local/Temp/resource.class;C:/Users/johorvat/AppData/Local/Temp/resource.jar" <- Works flawlessly without any errors and produces Java method return values on C++ side. 

如果我省略類文件並使用唯一的jar,則會發生同樣的情況。它只在我擁有它們或者獲得NoClassDefFoundError時纔有效。對我來說有點奇怪......

+0

定義「不能呼叫」和「停止工作」。 – EJP

+0

Core.jar的清單是否有一個類路徑條目命名其他jar文件? – EJP

+0

是的,它有。我還添加了清單的內容。 – Wrath

回答

0

不,你只需要提供一個正確構造的JAR文件 .class文件的層次結構。我建議您的jar文件中缺少某些內容,或者出現在錯誤的名稱或目錄下。

並注意NoClassDefError與ClassNotFoundException不相同。這意味着文件找到了,但它並不包含預期的類,例如錯誤的包裝或錯誤的包裝。

相關問題