未定义的对“JNI_CreateJavaVM”窗口的引用

时间:2013-06-05 02:23:16

标签: c++ windows java-native-interface

我正在尝试熟悉JNI API,但无法获得要编译的示例c ++程序。我得到了相同的样本来编译并在linux中运行(在下面的链接中发布问题后)但是无法在windows中编译它;我正在使用mingw g ++。我已经将所有包含路径更改为Windows路径,并且jni.h位于编译时,但不是jvm.dll。

undefined reference to `JNI_CreateJavaVM' linux

以下是我尝试编译的命令:

g++ -g -I"C:\Program Files (x86)\Java\jdk1.7.0_21\include" -I"C:\Program Files (x86)\Java\jdk1.7.0_21\include\win32" -L"C:\Program Files (x86)\Java\jdk1.7.0_21\jre\bin\server" callJava.cpp -ljvm

和...

**same as above with the additional** : -L"C:\Program Files (x86)\Java\jdk1.7.0_21\lib"

我得到的错误是:

undefined reference to `_imp__JNI_CreateJavaVM@12'

和正在编译的cpp:

#include <jni.h>

int main(){

    //firstTest();
    JavaVM *jvm;
    JNIEnv *env;

    JavaVMInitArgs vm_args;
    JavaVMOption options[1];
    options[0].optionString = "-Djava.class.path=C:/Users/Ron/Dropbox/jni/simple/ctojava/win";
    vm_args.version = JNI_VERSION_1_6;
    vm_args.options = options;
    vm_args.nOptions = 1;
    vm_args.ignoreUnrecognized = JNI_FALSE;

    int res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);

    jclass cls = env->FindClass("Hello");
    jmethodID mid = env->GetStaticMethodID(cls, "staticInt", "(I)I");
    env->CallStaticVoidMethod(cls, mid,10);

    jvm->DestroyJavaVM();
}

我看了很多例子,但仍然无法找到解决方案。任何帮助表示赞赏!

UPDATE :我很确定找到了jvm.dll,因为如果我删除-L“path_to_jvm”,那么我会收到错误:

mingw32/bin/ld.exe: cannot find -ljvm

就像我说的,这个确切的方法适用于linux,我还缺少什么用于Windows?

2 个答案:

答案 0 :(得分:3)

您遇到的问题可简要概括为名称装饰问题。链接器无法找到具有给定名称的函数,因为它在jvm.dll

中的装饰方式不同

查看您遇到的初始错误:

undefined reference to '_imp__JNI_CreateJavaVM@12'

它暗示了两件事:

  1. 末尾的@12后缀表示JNI_CreateJavaVM假设使用stdcall约定。
  2. _imp_前缀表示此函数来自导入库,导入库重定向到外部加载的dll,导出该导出表中的此函数。
  3. jni.h中的函数原型:

    _JNI_IMPORT_OR_EXPORT_ 
    jint JNICALL JNI_CreateJavaVM(JavaVM **, void **, void *);
    

    在预处理后可能看起来像这样:

    __declspec(dllimport) jint __stdcall
    JNI_CreateJavaVM(JavaVM **, void **, void *);
    

    现在,mingw附带的gnu链接器可以直接使用来自.a,msvc的COFF格式.lib.dll的符号。在原始命令中,它只在提供的搜索路径中找到jvm.dll-L ...),因此它尝试使用它。

    问题是在jvm.dll导出表中,JNI_CreateJavaVM函数是未装饰的,因此它看起来像一个cdecl函数。此名称与链接器所需的名称不匹配,因此您会收到未定义的引用错误。

    通过查看Java Dev Kit,它在jdk1.7.0_21\lib\jvm.lib包含一个导入库,该库具有此符号的正确名称。您修改后的命令有效,因为通过将-L jdk1.7.0_21\lib添加到搜索路径,它现在链接到jvm.lib而不是jvm.dll

答案 1 :(得分:2)

知道了!在阅读下面的帖子之后,我能够使用编译命令中的附加链接编译和运行示例,以便链接jvm.lib:

-L"C:\Program Files (x86)\Java\jdk1.7.0_21\lib"

链接:Linking JNI to visual studio 2008

我不是c / c ++专家,所以如果有人想解释为什么当它不在linux中时需要这个附加链接,我很乐意接受你的回答。