使用JNI在.jar文件中查找Java类

5

我正在编写一个程序,其中我使用JNI从C++代码调用Java函数。如果我直接使用.class文件,则我的程序可以正常运行,但是当我将它添加到一个jar文件中时,FindClass会失败。例如,以下内容可以正常工作:

    std::string stdOpt = "-Djava.class.path=<path_to_jar>/dependency.jar;<path_to_class>";

    boost::scoped_array<char> opt(new char[stdOpt.size() + 1]);
    std::copy(stdOpt.begin(), stdOpt.end(), opt.get());
    opt[stdOpt.size()] = '\0';
    options[0].optionString = opt.get();

    JavaVMInitArgs vm_args;
    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(&m_pJavaVirtualMachine, (void**)&m_pJavaEnvironment, &vm_args);
    if (status != JNI_OK)
        throw std::logic_error("Cannot start Java Virtual Machine");

    m_class = m_pJavaEnvironment->FindClass("MyClass");
    if(m_class == 0)
        throw std::logic_error("Cannot find Java class");

但是这一个失败了。
    std::string stdOpt = "-Djava.class.path=<path_to_jar>/dependency.jar;<path_to_jar>/myjar.jar";

    boost::scoped_array<char> opt(new char[stdOpt.size() + 1]);
    std::copy(stdOpt.begin(), stdOpt.end(), opt.get());
    opt[stdOpt.size()] = '\0';
    options[0].optionString = opt.get();

    JavaVMInitArgs vm_args;
    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(&m_pJavaVirtualMachine, (void**)&m_pJavaEnvironment, &vm_args);
    if (status != JNI_OK)
        throw std::logic_error("Cannot start Java Virtual Machine");

    m_class = m_pJavaEnvironment->FindClass("MyClass");    //m_class=NULL
    if(m_class == 0)
        throw std::logic_error("Cannot find Java class");  //throwing exception 

当我尝试从 .jar 中获取 Java 类时,是否有任何差异?出了什么问题?有什么想法吗?


如果您尝试从 dependency.jar 中查找类会发生什么?FindClass() 方法是否成功? - c.s.
是的,我已经尝试过了,它成功地找到了一个类。 - nabroyan
在这种情况下,请添加一个 SSCCE,以便我们可以在本地运行和测试。 - c.s.
2个回答

5
如果您的类在一个包中,调用FindClass时包括包名而不是类路径。
 m_class = m_pJavaEnvironment->FindClass( "com/mycompany/mypackage/MyClass" );

我知道,但是我的类不属于任何包。 - nabroyan
如果您没有指定一个包,那么它就在一个未命名的包中。如果我没记错,未命名的包有一些奇怪之处。我建议尝试将其放入一个包中,看看是否有所不同。拥有一个命名的包也是有用的,可以避免名称冲突。 - Andy Thomas

3
事实证明,问题不在代码中,代码是好的。问题出在制作 .jar 文件上。我正在使用 Visual Studio,并将自动编译 .java 文件为 .class 文件,并将 .class 文件添加到 .jar 文件中,我已经将其添加到项目的预构建事件中。因此,在制作 .jar 文件之前,我应该指定当前目录,如下所示:
cd "<_directory_where_.class_file_is_located>" jar cf myjar.jar MyClass.class
否则,MyClass.class 将与其绝对路径的文件夹一起添加到 .jar 文件中,FindClass() 函数将失败。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接