一、首先,编写一个包含native方法的类:
public class SayLibrary
{
public native void say(String message);
}
二、然后在linux下,先用javac命令将该类编译成class文件,再用javah命令编译该类,得到一个h头文件
javah -jni SayLibrary.java
生成SayLibrary.h
三、然后编写对应的C文件 SayLibrary.c
#include "SayLibrary.h"
/*
* Class: SayLibrary
* Method: say
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_SayLibrary_say
(JNIEnv *env, jobject obj, jstring str)
{
const char* msg = (*env)->GetStringUTFChars(env, str, 0);
printf("%s\n",msg);
(*env)->ReleaseStringUTFChars(env, str, 0);
}
四、接下来,就要用gcc来编译动态链接库了
gcc SayLibrary.c -I/root/java7/include/ -I/root/java7/include/linux -fPIC -shared -o libSayLibrary.so
-I中是gcc指定头文件路径的参数,这里需要包含jni的位置,以及linux下编译jni需要的头文件位置。
注意,输出的库文件一定要以lib开头,否则后面在java中使用System.loadLibrary(“库名”)时会找不到这个库。
五、在java中调用这个库
public class Main
{
static
{
System.out.println(System.getProperty("java.library.path"));
// System.load("/root/project/java/SayLibrary.so");
System.loadLibrary("SayLibrary");
}
public static void main(String[] args)
{
SayLibrary lib = new SayLibrary();
lib.say("Hello JNI, I'm coming...");
}
}
在这个例子中,我生成的动态链接库文件名是libSayLibrary.so, 在调用System.loadLibrary()方法时,只用到了SayLibrary这个字符串,没有lib开头和.so了。
如果文件名不以lib开头,则在linux下会找不到这个库,即便你把库路径加到了java.library.path中
六、执行这个java程序
将java程序用javac编译好后,在执行的时候将lib库加入到启动参数中(我是在当前路径下执行的,所以-Djava.library.path=./ )
java -Djava.library.path=./ Main (当然,你这样加了参数后,java默认的lib库路径就不在了,好点的做法是在代码用来修改)
执行后屏幕输出 Hello JNI, I'm coming...,成功!!!