前言:
初学java调用dll库时,经常出现无法加载库、找不到方法等错误(UnsatisfiedLinkError等)。本文对常见的问题进行详细的分析,给出较为完整的解决方案。
正文:
在java中写一个native方法,实现对dll的调用,一般过程如下:
public class Native {
static native void say(String src);
static{
System.loadLibrary("libname");
}
}
然后,用javah 命令生成头文件,得到:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Native */
#ifndef _Included_Native
#define _Included_Native
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Native
* Method: say
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Native_say
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
创建C项目(Eclipse平台),将上述的头文件拷贝过来,再写一个.c或者.cpp的文件来实现原生方法
#include "native.h"
JNIEXPORT void JNICALL Java_Native_say(JNIEnv* env, jclass clz, jstring src){
//....
}
build,得到dll文件,改成name.dll,放到java项目下即可。
经过以上方法,运气好的话,可能一次就成了。但也常见以下错误,我将其分为3类:
A类错误,找不到/无法加载dll文件:
0.java.lang.UnsatisfiedLinkError: no XXX in java.library.path
1.java.lang.UnsatisfiedLinkError: Can't load library
2.UnsatisfiedLinkError: XXXXXXX 不是有效的 Win32 应用程序。
B类错误,在所有成功加载的dll文件中,找不到要调用的方法:
0.java.lang.UnsatisfiedLinkError: Native.say(Ljava/lang/String;)V
C类错误,C.C/C++编译器找不到/无法解析jni.h头文件:
0.#include <jni.h>这里提示找不到头文件,以及方法声明那里提示语法错误。
D类错误,jvm版本与dll冲突:
0.ava.lang.UnsatisfiedLinkError:Can't load IA 32-bit .dll on a AMD 64-bit platform。这类错误好理解,就是32位jvm用了64位dll,或者反过来。也比较容易解决,通常换一个对应版本的dll就可以;或者换jdk版本,但比较麻烦。
以上4类问题,D类由于解决起来较为简单,不再讲解。
C类:C.C/C++编译器找不到/无法解析jni.h头文件
这类错误不属于我们代码编写问题,是编译平台的问题。只要能让编译平台知道去哪里找这个头文件就可以。eclipse的话,如果以mingw为C编译器,比较好的解决办法就是,把jdk目录下,include/jni.h和include/win32/jni_md.h放到mingw文件夹下,mingw版本号那个文件夹里的include中,比如我的目录是:D:\Cbianyi\mingw64\x86_64-w64-mingw32\include。如果是用VS6,可以在下图的位置添加jdk的上述目录:
如果是VS2017,设置include目录即可。个人推荐写C代码还是用VS的好,VS6也比eclipse要方便。<