有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

C++不能使用JNI使用外部java类

我无法通过JNI使用外部Java类。我将用一个玩具的例子来说明我的问题

这是我的Java类,它使用Apache Commons IO中的外部类FilenameUtils作为示例:

示例。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编译它,然后执行它。这是我得到的输出,这是正确的:

Before
foo
After

<> >当我使用JNI从C++调用java方法“BASE”时,问题就出现了。这是C++代码:

测试。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选项中再次指定了CLASSPATH。我还向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

然后执行这个编译程序。这是我现在得到的输出:

Before
Finished

方法“base”的执行在访问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时类路径的行为会有所不同


共 (1) 个答案

  1. # 1 楼答案

    所以问题很简单。使用$classpath或-cp指定类路径时,可以使用通配符

    但是如果类路径设置为“-Djava.class.path”通配符不起作用,则必须单独指定JAR和目录列表

    此外,“-Djava.class.path”覆盖$CLASSPATH