未定义的引用“JNI_CreateJavaVM”窗口 [英] undefined reference to `JNI_CreateJavaVM' windows

查看:2656
本文介绍了未定义的引用“JNI_CreateJavaVM”窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图熟悉JNI API,但是无法获取一个示例c ++程序来编译。我有相同的样本编译和运行在linux(post在下面的链接的问题后,但不能得到它编译在windows;我使用mingw g ++。我改变了所有的包含路径到Windows路径和jni.h正在编译时,而不是jvm.dll。



未定义引用`JNI_CreateJavaVM'linux



这里是我尝试使用编译的命令:

  g ++ -g -IC:\Program Files )\Java \jdk1.7.0_21\include-IC:\Program Files(x86)\Java\jdk1.7.0_21\include\win32-LC:\Program文件(x86)\Java\jdk1.7.0_21\jre\bin\servercallJava.cpp -ljvm 

和...

  **与上述相同**:-LC :\Program Files(x86)\Java\jdk1.7.0_21\lib

我得到的错误是:

 未定义引用`_imp__JNI_CreateJavaVM @ 12'

和正在编译的cpp:

  #include< ; jni.h> 

int main(){

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

JavaVMInitArgs vm_args;
JavaVMOption选项[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被找到,因为如果我删除-Lpath_to_jvm 那么我得到错误:

  mingw32 / bin / ld.exe:找不到-ljvm 

解决方案

你碰到的问题可以简单地总结为一个名称装饰问题。链接器找不到具有给定名称的函数,因为它在 jvm.dll 中的装饰不同。



查看您遇到的初始错误:

 未定义引用_imp__JNI_CreateJavaVM @ 12

它暗示了两件事:


  1. c $ c> @ 12 后缀表示 JNI_CreateJavaVM 假设使用stdcall约定。

  2. _imp _ 前缀表示此函数来自重定向到外部加载的dll的导入库,该函数在其导出表中显示此函数。

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 在您的原始命令中,它只在提供的搜索路径( -L ... )中找到 jvm.dll 它试图使用它。



问题是在 jvm.dll 导出表 c $ c> JNI_CreateJavaVM 函数未装饰,因此看起来像一个cdecl函数。



从Java开发工具包的角度看,它包含一个导入库 jdk1.7.0_21\lib\jvm.lib ,该符号具有适当的名称装饰。您修改的命令的工作原理是通过将 -L jdk1.7.0_21\lib 添加到它现在链接的搜索路径 jvm.lib 而不是 jvm.dll


I'm trying to get familiar with the JNI API but can't get a sample c++ program to compile. I got the same sample to compile and run in linux (after posting the question in the link below) but can't get it compiled in windows; I'm using mingw g++. I've changed all the include paths to windows paths and the jni.h is being located at compile time but not the jvm.dll.

undefined reference to `JNI_CreateJavaVM' linux

Here is the commands I've tried using to compile:

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

and...

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

The error I get is:

undefined reference to `_imp__JNI_CreateJavaVM@12'

and the cpp being compiled:

#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();
}

I've looked at many examples but still can't find a solution. Any help is appreciated!

UPDATE: I am pretty sure the the jvm.dll is being located because if I remove the -L"path_to_jvm" then I get the error:

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

Like I said, this exact approach works in linux, What else am I missing for windows?

解决方案

The issue you ran into can briefly be summed up as a name decoration problem. The linker couldn't find the function with the given name because it's decorated differently in the jvm.dll.

Looking at the initial error you got:

undefined reference to '_imp__JNI_CreateJavaVM@12'

it's hinting at two things:

  1. The @12 suffix at the end indicates that JNI_CreateJavaVM supposely uses the stdcall convention.
  2. The _imp_ prefix indicates that this function is from an import library that redirects to an externally loaded dll that has this function visible in its export table.

The function prototype in jni.h:

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

probably looks like this after preprocessing:

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

Now the gnu linker that comes with mingw can work with symbols from .a, msvc's COFF format .lib and .dll directly. In your original command, it only found jvm.dll in the search path provided (-L ...) so it tried to use that.

The problem is that in jvm.dll's export table the JNI_CreateJavaVM function is un-decorated so it looks like a cdecl function. This name doesn't match what the linker expects so you get the undefined reference error.

From looking at the Java Dev Kit, it includes an import library at jdk1.7.0_21\lib\jvm.lib which has the proper name decoration for this symbol. Your revised command works because by adding -L jdk1.7.0_21\lib to the search path it's now linking against jvm.lib and not jvm.dll.

这篇关于未定义的引用“JNI_CreateJavaVM”窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆