java语言使用jni调用本地接口

JAVA 调用 c语言动态库教程

1、首先我们先用eclipse建立项目,项目名为JNIDemo

建好项目之后,在src目录下创建我们的包com.fox.main

  1. 在com.fox.main包中定义两个Java类,一个是Main类,一个是Washer类。

package com.fox.main;

public class Main {

    public static void main(String[] args) {

        Washer washer = new Washer();

        if (!washer.is_Open()) {

             System.out.print("washer closed");

        }

    }

}

 

package com.fox.main;

public class Washer {

    public Washer(){}

    public native boolean open();//打开

    public native boolean close();//关闭

    public native boolean is_Open();//是否已经打开

    public native boolean is_error();//设备是否出错

    static{

        System.loadLibrary("washer");//加载c动态库,注意这里没有lib前缀和.so后缀

        //System.load("/usr/lib/libwasher.so");//使用绝对路径加载c动态库

    }

}

  1. 进入Washer所在目录,使用javac命令将Washer.java编译为Washer.class文件

fox@fox-QTS5:~/workspace/JNIDemo/src/com/fox/main$ javac Washer.java

  1. 退到src目录下,使用javah命令将Washer.class编译为C语言的头文件

注意:这里我们编译Washer.class时不需要写.class后缀名。

(文件名会根据包名的不同而不同,这也就是我们为什么要退到src目录下的原因)

fox@fox-QTS5:~/workspace/JNIDemo/src$ javah com.fox.main.Washer

  1. 这样就在src目录下产生了c语言的头文件com_fox_main_Washer.h,我们需要自己编写.c源文件来实现该头文件中的函数。

注意:源头文件中的函数声明可能没有形参的名字

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *, jobject);

我们在定义该函数时应该添加形参名字,即使我们不使用形参也要添加,否则编译不通过

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *env, jobject jobj){

    //实现代码

    return 0;

}

  1. 这里对源文件的名字没有要求,但为了便于识别,我们将源文件的名字写为:com_fox_main_Washer.c。

#include "com_fox_main_Washer.h"

 

#ifdef __cplusplus

extern "C" {

#endif

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *env, jobject jobj){

    return 0;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_close

  (JNIEnv *env, jobject jobj){

    return 1;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_is_1Open

  (JNIEnv *env, jobject jobj){

    return 0;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_is_1error

  (JNIEnv *env, jobject jobj){

    return 0;

}

#ifdef __cplusplus

}

#endif

  1. 编写完我们的.c源文件后,我们需要将其编译为.o的目标代码

注意,这里需要指定-fPIC选项来说明要编译为与位置无关的目标代码。

-I/usr/lib/jvm/java-8-oracle/include选项用来引入jni.h这个头文件,这个头文件在java的jdk目录下,自己可以根据自己的文件路径进行相应的修改。

-I/usr/lib/jvm/java-8-oracle/include/linux选项也是引入头文件jni_md.h。

fox@fox-QTS5:~/workspace/JNIDemo/src$ gcc -fPIC -c com_fox_main_Washer.c -I/usr/lib/jvm/java-8-oracle/include -I/usr/lib/jvm/java-8-oracle/include/linux

  1. 我们在通过gcc将目标代码编译为.so的动态库

fox@fox-QTS5:~/workspace/JNIDemo/src$ gcc -shared -o libWasher.so com_fox_main_Washer.o

-shared 选项是将目标代码编译为共享库也就是动态库, -o 表示输出文件名

根据Linux的动态库命名规范我们应将动态库命名为:libXXX.so的形式。例如这里的libWasher.so。而在Java代码中加载是则不需要带lib前缀。 后边跟的是要编译的目标代码。

到此,动态库就制作完成了,但是当你通过eclipse运行Main中的主程序时会报异常,因为是我们自己做到,没有配置到系统目录,这样Java程序找不到它就报异常。

  1. 将我们制作好的动态库拷贝到系统库,当然得需要root权限。

fox@fox-QTS5:~/workspace/JNIDemo/src$ sudo cp libWasher.so /usr/lib

配置好之后就可以通过eclipse运行Java程序了,正常显示应打印:washer closed

 

通过eclipse导出可运行的Java程序

  1. 首先我们需要将Java项目的原文件打包成可执行的.jar包。

在项目列表中选中要打包的项目,右键,点击export选项。

选择Java中的Runnable JAR File选项,点击 下一步

选中运行配置的main方法类,在export destination中选择导出路径和导出的文件名,

也就相当于exe文件。在下边选择export required libraries选项。点击finish完成。

  1. 然后我们就可以通过java命令执行该程序了,在导出的.jar文件目录下打开终端,执行命令java -jar 文件名.jar来执行该程序。

fox@fox-QTS5:~/download$ java -jar washer.jar

  1. 我们可以将该命令写进脚本中,配置开机启动项。

写启动脚本文件vim washer

#! /bin/sh

java -jar /home/fox/washer.jar

将这个脚本文件中丢到/etc/init.d/目录中并添加可执行权限

sudo mv ./washer /etc/init.d/

sudo chmod 715 xxxx

在/etc/rc_n.d目录中添加向相应的软连接。这里添加到/etc/rc3.d目录中。

注意这里rc3.d中的命名规范:S_nn_服务名,K_nn_服务名

S表示该级别启动时需要开启的服务,K表示级别启动时需要关闭的服务

ln -s /etc/init.d/washer /etc/rc3.d/S03washer

测试服务是否正常,在rc3.d中执行脚本

./S03washer

如果成功打印信息说明脚本配置成功。

 

 

 

通过命令行导出可运行的Java程序

由于设备无法显示的原因,当我们通过命令行来进行Java程序开发的时候,如何将其编译成可运行的.jar包。

1、Java程序的编写,建立包名com.fox.main,其对应的目录为/com/fox/main

在com/fox/main中添加两个Java文件

Main.java文件

package com.fox.main;

public class Main {

    /**

     * @param args

     */

    public static void main(String[] args) {

        Washer washer = new Washer();

        if (!washer.is_Open()) {

           System.out.print("washer closed");

        }else{

           System.out.print("washer opened");

        }

    }

}

Washer.java文件

package com.fox.main;

public class Washer {

    public Washer(){}

    public native boolean open();

    public native boolean close();

    public native boolean is_Open();

    public native boolean is_error();

    static{

        System.load("/usr/local/lib/libWasher.so");//注意这里的绝对路径

    }

}

  1. 编译这两个文件

先说一下目录结构src/com/fox/main/,在src目录下执行命令

javac com/fox/main/*.java

上面这条指令直接将com.fox.main中的所有Java文件一起编译,最好这样编译,因为当各个类中有依赖关系的时候,单独编译会报错。

  1. 生成C语言的.h文件,在src目录下

Javah com.fox.main.Washer

上面这条指令会将com/fox/main/Washer.class文件编译出com_fox_main_Washer.h文件并保存到当前目录(也就是src目录中)

  1. 编写.c文件实现头文件中的所有函数,最好通过下面的方式实现,因为.h文件中的函数名很长,自己写容易写错。

cp com_fox_main_Washer.h com_fox_main_Washer.c       //将.h文件复制一份

vim com_fox_main_Washer.c                              //修改里面的代码

修改后的代码如下

#include "com_fox_main_Washer.h"

 

#ifdef __cplusplus

extern "C" {

#endif

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *env, jobject obj){

        return 1;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_close

  (JNIEnv *env, jobject obj){

        return 0;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_is_1Open

  (JNIEnv *env, jobject obj){

        return 1;

}

 

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_is_1error

  (JNIEnv *env, jobject obj){

        return 0;

}

 

#ifdef __cplusplus

}

#endif

注意:源头文件中的函数声明可能没有形参的名字

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *, jobject);

我们在定义该函数时应该添加形参名字,即使我们不使用形参也要添加,否则编译不通过

JNIEXPORT jboolean JNICALL Java_com_fox_main_Washer_open

  (JNIEnv *env, jobject jobj){

    //实现代码

    return 0;

}

  1. 将com_fox_main_Washer.c编译为.o的目标代码。

gcc -fPIC -c com_fox_main_Washer.c

这里的-fPIC选项是将代码编译为与位置无关的目标代码。

这样当多个进程使用该动态库时,只需要加载一份就可以了。

6、然后将目标代码编译为动态库

gcc -shared -o libWasher.so com_fox_main_Washer.o

这是就生成了libWasher.so的动态库

我们可以将

 

通过命令行打包Java程序

1、首先我们先编译Java项目

javac com/fox/main/*.java

  1. 编写Java启动的配置文件MANIFEST.MF

Manifest-Version: 1.0

Class-Path: .

Main-Class: com.fox.main.Main

  1. 在src目录下打包Java程序

jar cvfm Washer.jar ./MANIFEST.MF com/

会在src目录中生成Washer.jar的文件

  1. 运行该Java程序

java -jar Washer.jar

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值