问题描述
我试图熟悉JNI API,但是无法获取一个示例c ++程序来编译。我有相同的样本编译和运行在linux(post在下面的链接的问题后,但不能得到它编译在windows;我使用mingw g ++。我改变了所有的包含路径到Windows路径和jni.h正在编译时,而不是jvm.dll。
这里是我尝试使用编译的命令:
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
它暗示了两件事:
c $ c> @ 12
后缀表示JNI_CreateJavaVM
假设使用stdcall约定。
_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
它试图使用它。
问题是在
函数未装饰,因此看起来像一个cdecl函数。jvm.dll
的导出表 c $ c> JNI_CreateJavaVM
从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:
- The
@12
suffix at the end indicates thatJNI_CreateJavaVM
supposely uses the stdcall convention.- 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 foundjvm.dll
in the search path provided (-L ...
) so it tried to use that.The problem is that in
jvm.dll
's export table theJNI_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 againstjvm.lib
and notjvm.dll
.这篇关于未定义的引用“JNI_CreateJavaVM”窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!