JNI C++为什么我还需要.class和.jar

JNI C++ Why do I need .class and .jar also?

本文关键字:class jar C++ 为什么 JNI      更新时间:2023-10-16

我有一个非常直接的代码,可以从C++通过JNI调用JAVA函数,但只有当我提供编译的.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调用任何函数。当我再次设置时,一切都很好。我是否也需要编译后的源代码和带有依赖性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,里面有编译好的类,还有一个lib文件夹,里面有外部jar文件

现在来看实际有问题的部分。如果稍后在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

@编辑(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时,它才有效。对我来说有点奇怪…

否。您只需要提供一个构造正确的JAR文件.class文件的层次结构。我建议您的jar文件中缺少某些内容,或者存在于错误的名称或目录下。

请注意,NoClassDefError与ClassNotFoundException不同。这意味着文件已被找到,但它不包含所需的类,例如错误的大小写或错误的包。