JAVA代码:
public class Wjb {
static {
System.load("D:"+ File.separator+"wjb.dll");
}
public native static void hello();
public static void main(String[] args) {
hello();
}
}
C++代码:wjb.cpp
#include <stdio.h>
#include "com_apply_aspect_Wjb.h"
#include <jni.h>
#include <jni_md.h>
JNIEXPORT void JNICALL Java_com_apply_aspect_Wjb_hello
(JNIEnv *, jclass)
{
printf("Hello world!\n");
return;
}
com_apply_aspect_Wjb.h文件如何生成
可以使用javah命令,例如:
javah com.apply.aspect.Wjb
javah后面的最好写成全类名,命令行进入class文件夹的根路径。
cpp文件夹编译成dll文件夹:
gcc -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -shared -o wjb.dll wjb.cpp
如果程序报错:
意思是库文件已经成功载入了,但是没有找到相匹配的方法。可是我们明明实现了这个方法的呀?原来程序在调用动态库的时候,没有我们想象中的那么简单,而且不同的编译器做法不一样,windows版java中调用jni遵从的是vc的调用方式,和我们用的MinGW GCC默认格式不一致。我们需要调整一下参数,(注意其中的--kill-at)
gcc -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -shared -Wl,--kill-at -o wjb.dll wjb.cpp
如果JDK装在C:\Program Files目录下,可能会因为空格而找不到目录可将include里的jni.h和jni_md.h复制到别的文件夹如-ID:/jni(特别强调,-I后面只能是文件夹)
本人的实例:
gcc -ID:\jni -ID:\jniMd -shared -Wl,--kill-at -o wjb.dll wjb.cpp
运行JAVA程序,报错,64位的平台无法加载32位dll文件。
java.lang.UnsatisfiedLinkError: D:\wjb.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at com.apply.aspect.Wjb.<clinit>(Wjb.java:10)
Exception in thread "main"
于是立马下载了64位的Mingw,环境变量修改成64位的Mingw,重新编译。完美运行,请看下图。
有几个需要注意的地方:
如果要用IDEA运行的话,那么wjb.cpp的头文件就得这么引
#include "D:\wjb\gameadminv2\target\classes\com_apply_aspect_Wjb.h"
生成.h的文件也得这么写,命令行进入项目的class根路径下,我这里是:D:\wjb\gameadminv2\target\classes,然后再用下面的命令生成.h文件。
javah com.apply.aspect.Wjb