Linux下Jni 调用

JAVA可以通过JNI接口访问本地的动态连接库,从而扩展JAVA的功能。使用JAVA JNI接口主要包括以下步骤:

(1)编写JAVA代码,注明要访问的本地动态连接库和本地方法;

(2)编译JAVA代码得到.class文件;

(3)使用javah -jni 生成该类对应的C语言.h文件;

(4)使用C/C++实现(3)生成的.h文件中声明的各函数;

(5)编译C/C++实现代码生成动态连接库。

一、没有包的情况
1. Java代码
首先,实现的是Java本地接口HelloWorld.java,代码如下所示:
 
class HelloWorld {
    public native void sayHello();
   static {
       System.loadLibrary("HelloWorld");
    }
   public static void main(String[] args) {
        (new HelloWorld()).sayHello();
    }
}
2. 生成class文件
$ javac HelloWorld.java
3. 生成C语言的头文件
$ javah -jni HelloWorld
 
生成的HelloWorld.h的头文件,内容如下:
 
/* DO NOT EDIT THIS FILE - it is machinegenerated */
#include <jni.h>
/* Header for class HelloWorld */
 
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 *Class:     HelloWorld
 *Method:    sayHello
 *Signature: ()V
 */
JNIEXPORT void JNICALLJava_HelloWorld_sayHello
 (JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif
4. .c/.cpp的源文件实现
HelloWorld.c
#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>
 
JNIEXPORT void JNICALLJava_HelloWorld_sayHello (JNIEnv *env, jobject obj) {
   printf("Hello,the World!!!");
}
5. 将.c文件,编译成.o文件
gcc -fPIC -D_REENTRANT-I/usr/java/jdk1.7.0_51/include/ -I/usr/java/jdk1.7.0_51/include/linux  -c HelloWorld.c
注: /usr/java/jdk1.7.0_51/include/ 是jni.h头文件所在的路径
/usr/java/jdk1.7.0_51/include/linux 是jni_md.h所在的路径
6. 将.o文件,编译成.so库文件
gcc -shared HelloWorld.o -o libHelloWorld.so
注:和windows下不同,linux的库文件必须是以libxxx.so形式命令的(或者libxxx.so.y,y是版本号),lib前缀是为了系统能够识别它,xxx是java代码System.loadLibrary("xxx");中引用库的名字。
7. 配置路径
将生成的HelloWorld.so文件拷贝到java的加载库LD_LIBRARY_PATH指向的路径中。
前提是你有足够的权限。若没有sudo权限的同学,用下面的方法:
1) 在/home下建立一个用来存放.so库文件的目录,比如/home/hhiiuxx/lib
2) 把libgoodluck.so文件拷贝到该目录下
3) 打开Terminal,运行如下命令
export LD_LIBRARY_PATH=/home/hadoop/Documents/jni
export LD_LIBRARY_PATH=/home/hadoop/Documents/jni/com/hdu/qing
只在当前shell下有效...
8. 运行Jni
$ java HelloWorld
$ java com.hhiiuxx.test.HelloJNI
java com.hdu.qing.HelloWorld
package com.hdu.qing;
com_hdu_qing_HelloWorld
gcc -shared com_hdu_qing_HelloWorld.o -o libHelloWorld.so
gcc -fPIC -D_REENTRANT-I/usr/java/jdk1.7.0_51/include/ -I/usr/java/jdk1.7.0_51/include/linux  -c com_hdu_qing_HelloWorld.c
二、有包的情况下
1. Java代码
HelloWorld.java,我将代码放在/home/hadoop/Documents/jni/com/hdu/qing下,代码如下所示:
package com.hdu.qing;
class HelloWorld {
    public native void sayHello();
   static {
       System.loadLibrary("HelloWorld");
    }
   public static void main(String[] args) {
       (new HelloWorld()).sayHello();
    }
}
2. 生成class文件
在/home/hadoop/Documents/jni,也就是包前的路径下执行:
$ javac com/hdu/qing/HelloWorld.java
生成的HelloWorld.class文件会在/home/hadoop/Documents/jni/com/hdu/qing下
3. 生成C语言的头文件
在/home/hadoop/Documents/jni,也就是包前的路径下执行:
$ javah com.hdu.qing.HelloWorld
 
生成的com_hdu_qing_HelloWorld.h的头文件,在/home/hadoop/Documents/jni目录下,内容如下:
 
/* DO NOT EDIT THIS FILE - it is machinegenerated */
#include <jni.h>
/* Header for class com_hdu_qing_HelloWorld*/
 
#ifndef _Included_com_hdu_qing_HelloWorld
#define _Included_com_hdu_qing_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 *Class:     com_hdu_qing_HelloWorld
 *Method:    sayHello
 *Signature: ()V
 */
JNIEXPORT void JNICALLJava_com_hdu_qing_HelloWorld_sayHello
 (JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif
4. .c/.cpp的源文件实现
在/home/hadoop/Documents/jni目录下,创建com_hdu_qing_HelloWorld.c文件,代码如下:
#include <jni.h>
#include"com_hdu_qing_HelloWorld.h"
#include <stdio.h>
 
JNIEXPORT void JNICALL Java_com_hdu_qing_HelloWorld_sayHello (JNIEnv *env, jobjectobj) {
   printf("Hello,the World!!!");
}
注:红色注明的部分为包的名字
5. 将.c文件,编译成.o文件
在/home/hadoop/Documents/jni,也就是包前的路径下执行:
gcc -fPIC -D_REENTRANT-I/usr/java/jdk1.7.0_51/include/ -I/usr/java/jdk1.7.0_51/include/linux  -c com_hdu_qing_HelloWorld.c
注: /usr/java/jdk1.7.0_51/include/ 是jni.h头文件所在的路径
/usr/java/jdk1.7.0_51/include/linux 是jni_md.h所在的路径
6. 将.o文件,编译成.so库文件
在/home/hadoop/Documents/jni,也就是包前的路径下执行:
gcc -shared com_hdu_qing_HelloWorld.o -o libHelloWorld.so
注:和windows下不同,linux的库文件必须是以libxxx.so形式命令的(或者libxxx.so.y,y是版本号),lib前缀是为了系统能够识别它,xxx是java代码System.loadLibrary("xxx");中引用库的名字。
7. 配置路径
将生成的HelloWorld.so文件拷贝到java的加载库LD_LIBRARY_PATH指向的路径中。
前提是你有足够的权限。若没有sudo权限的同学,用下面的方法:
1) 在/home下建立一个用来存放.so库文件的目录,比如/home/hhiiuxx/lib
2) 把libgoodluck.so文件拷贝到该目录下
3) 打开Terminal,运行如下命令
export LD_LIBRARY_PATH=/home/hadoop/Documents/jni/com/hdu/qing
只在当前shell下有效...
8. 运行Jni
$ java com.hdu.qing.HelloWorld