我在通过JNI使用外部Java类时遇到问题。我用玩具示例来说明我的问题。
这是我的Java类,作为示例使用Apache Commons IO的外部类FilenameUtils:
Example.java
import org.apache.commons.io.FilenameUtils;
class Example {
static void base () {
String str = "/usr/foo.bar";
System.out.println("Before");
try {
System.out.println(FilenameUtils.getBaseName(str));
}
catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("After");
}
public static void main(String[] args) {
base();
}
}
我的类路径设置为$ CLASSPATH:
export CLASSPATH=".:/Applications/eclipse/plugins/*"
我用javac编译它,然后执行它。这是我得到的输出,这是正确的:
在
FOO
之后
当我调用Java方法" base"时会出现问题。来自C ++使用JNI。这是C ++代码:
TEST.CPP
#include <jni.h>
#include <cstring>
int main()
{
JavaVMOption options[1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
jclass cls;
jmethodID method;
jobject simpleJNITestInstance;
options[0].optionString = "-Djava.class.path=.:/Applications/eclipse/plugins/*";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
long status = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
if (status != JNI_ERR)
{
cls = env->FindClass("Example");
if (cls != 0)
{
method = env->GetStaticMethodID(cls, "base", "()V");
env->CallStaticVoidMethod(cls, method, 5);
}
jvm->DestroyJavaVM();
}
printf("Finished\n");
return 0;
}
虽然我不认为它是必要的,因为它已经配置了$ CLASSPATH,我再次指定了VM选项中的类路径。我还在CallStaticVoidMethod函数中添加了一个参数5,因为我不知道如何指定零参数。 Java方法没有收到任何参数,因此会被忽略。
然后我编译这个C ++代码:
g++ -o test \
-I/Library/Java/JavaVirtualMachines/jdk1.7.0_72.jdk/Contents/Home/include \
-I/Library/Java/JavaVirtualMachines/jdk1.7.0_72.jdk/Contents/Home/include/darwin \
-L/Library/Java/JavaVirtualMachines/jdk1.7.0_72.jdk/Contents/Home/jre/lib/server/ \
test.cpp \
-ljvm
执行此编译程序。这是我现在得到的输出:
在
完了
执行方法&#34; base&#34;只是在访问getBaseName方法时停止。没有引发异常,它只是停止执行,并返回到本机代码。
为什么无法执行FilenameUtils.getBaseName()方法?
我的机器运行的是Mac OS 10.10 Yosemite,Java 1.7.0.72 64位。
提前致谢。
更新
我尝试将commons-io-2.4.jar直接包含在类路径中,现在该程序可以运行:
options[0].optionString = "-Djava.class.path=.:/Applications/eclipse/plugins/commons-io-2.4/commons-io-2.4.jar";
现在我的问题是,为什么使用JNI时类路径的行为会有所不同?
答案 0 :(得分:1)
所以问题很简单。使用$ CLASSPATH或-cp指定类路径时,可以使用通配符。
但是如果类路径设置为“-Djava.class.path”,则通配符不起作用,则必须单独指定jar和目录列表。
此外,“ - Djava.class.path”会覆盖$ CLASSPATH。