JNI之JAVA调用C程序(linux环境)

1 篇文章 0 订阅
1 篇文章 0 订阅

JNI之JAVA调用C程序(linux环境)

因业务需求,需要对上传的文件做crc文件冗余校验,由于规则比较特殊一般JAVA的CRC校验无法得到正确的crc值,因此考虑使用JAVA调用C的方法实现。

JNI介绍

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。 从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。JNI的调用一般有两种,一种是在windows环境下的dll文件,另一种是在linux环境下的so文件,由于公司提供的是linux下的C文件,因此这里主要讲解linux下的调用。

大体流程

首先需要明确的调用的基本流程:
①首先需要有个java类去读取本地文件
②我们需要通过编译获得该类的.class文件
③然后根据.class文件去生成相对应的.h文件(主要就是生成调用的方法)
④再通过写好的.c程序在里面引入.h文件中的方法(这一点很像是java接口的实现)
⑤最后根据.c文件去生成.o和.so文件,最终生成的.so文件就是我们需要去读取的本地文件(注:linux下是使用.so文件,windows下则是需要使用.dll文件

具体实现

首先我们创建一个空的maven项目把它放到linux下(crcTest)
在这里插入图片描述
在这个目录下新建CrcTest类如下 /usr/local/java/crcTest/src/main/java/cn/joral

package cn.joral;

/**
 * @ProjectName: vue
 * @Package: cn.joral.util
 * @ClassName: cn.joral.util.CrcUtil
 * @Author: Administrator
 * @Description: ${description}
 * @Date: 2019/10/22 19:45
 * @Version: 1.0
 */
public class CrcTest {
    static
    {
        System.load( "/usr/local/java/cn_joral_CrcTest.so" );
    }
    private static native int queryCrc(String path);

    public static void main(String[] args) {
        System.out.println(queryCrc("/root/CRC.bin"));
    }
}

这里加载静态文件可以有两种方法System.load 和 System.loadLibrary
System.load 参数为库文件的绝对路径,可以是任意路径。
System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
后者需要配置比较麻烦,这里就直接使用绝对路径

接着就是通过指令生成.class文件 在javac CrcTest.java
在这里插入图片描述
在Xshell远程连接后,直接定位到目录通过指令生成.class文件(注意:生成后需要把.class文件移到对应target目录下 以下为我的目录可以做个参考 /usr/local/java/crcTest/target/classes/cn/joral

仅接着我们定位到target目录下去生成.h文件在这里插入图片描述
按照图片中的指令即可生成.h文件(这里注意linux下生成可能和windows不太一样,如果是linux下可参考我生成的方式
说道这里我们用记事本打开看一下生成的.h文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_joral_CrcTest */

#ifndef _Included_cn_joral_CrcTest
#define _Included_cn_joral_CrcTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_joral_CrcTest
 * Method:    queryCrc
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_cn_joral_CrcTest_queryCrc
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

你会发现其实这个.h文件很简单,主要就是与本地方法相匹配的一个调用方法,jstring即为我们传的参数,jint即为返回值。

接下来需要我们将写好的c程序放到同一目录下(target目录下)

#include <stdio.h>
#include "cn_joral_CrcTest.h"//引入.h文件同名
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
JNIEXPORT jint JNICALL Java_cn_joral_CrcTest_queryCrc
  (JNIEnv *env, jobject obj, jstring s)
{
	char * str = (char *) (*env)->GetStringUTFChars(env, s, 0); 
	printf("str :  %s \n",str);//获取到传来的string参数 
	//具体业务代码部分
	return 1;//返回值
}

这里具体业务代码就不做展示了(注意点:
①引入文件必须为生成的.h文件
②方法名参数必须一致

在这里插入图片描述
我们将.c文件和.h文件都放在target目录下,然后在该目录下执行下面两句命令即可生成对应的.o文件和.so文件(生成时需要用到jdk相关文件)
生成最终的.so文件基本上已经算是已经成功了。最后我们根据CrcTest.java中的配置移动.so文件到相关路径下。
在这里插入图片描述
接着我们试一下是否成功,依然还是在target目录下运行.class文件在这里插入图片描述
我们可以看到.c中打印的参数和返回值,和我们所期待的一样,说明我们成功了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值