我有一個非常直接的代碼來通過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時纔有效。對我來說有點奇怪......
定義「不能呼叫」和「停止工作」。 – EJP
Core.jar的清單是否有一個類路徑條目命名其他jar文件? – EJP
是的,它有。我還添加了清單的內容。 – Wrath