Java通过JNI调用C/C++动态链接库

Java可以通过JNI(Java Native Interface)来调用本地库,从而解决一些需要使用C/C++来提高效率但却需要使用JAVA调用的场景,例如opencv库编写的图像处理函数,需要使用spark等大数据框架来调用。

关于
演示一个Hello world的C++通过java调用的过程,系统环境为linux,编译工具使用g++,java版本为jdk1.8。
JNI调用C/C++基本步骤很简单:

java代码中声明带有native修饰的类方法,该native方法只是在java中进行声明,而不进行实现,在需要调用navtive方法之前进行system.loadLibrary(“xxx”),然后通过类调用方法xxx即可
使用javah从java的class文件生成与native函数相应的头文件
通过引用含有native方法声明的头文件,采用C++编写native方法的实现,并将其编译为动态链接库
然后正常对java编译并执行即可
下面进行详细分析

Java代码
Java代码如下:

//文件名为hello.java
public class hello
{
    public native void helloWorld();  //声明本地库中的函数
    public static void main(String[] args) {
        System.loadLibrary("helloWorld"); //载入本地库
        hello t = new hello();
        t.helloWorld();  //调用本地库中的函数
    }
}

注意,如果本地库中有多个函数,只需要调用一次System.loadLibrary即可
调用库中只需要写库的名字,windows下不需要添加后缀.dll,linux下不需要添加前面的lib和后缀.so
此时可以直接使用javac hello.java编译生成class字节码,因为此时实际上java编译器并不会去查看是否已经有了函数helloWorld的实现。

生成头文件
运行以下命令生成头文件

javah hello
很多教程中提及此命令执行之前需要先使用javac对代码编译,其实可以直接使用javah来从java源代码生成头文件,javah会自动生成临时的class文件(该class文件不会在源文件夹中保存),然后再生成头文件。我通常是直接生成头文件,最后再编译java源代码为class,以避免虽时可能需要修改java源代码。
注意,不需要添加后缀.java,因为它实际上是从class文件生成的头文件,然后文件夹中会生成头文件hello.h,内容如下:

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

#ifndef _Included_hello
#define _Included_hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     hello
 * Method:    helloWorld
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_hello_helloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

可以看到在第15、16行有一个名为Java_hello_helloWorld的函数声明,其中名称以Java开头,包含了包名、类名和函数名,并以下划线分隔,形如Java_{package_and_classname}_{function_name}(JNI arguments)。后面编写C/C++代码时的函数名字必须与此处一样。
其中的2个参数作用是:

JNIEnv*:用于引用JNI环境,该指针变量可以访问所有JNI函数
jobject:引用this Java对象,也就是可以用来访问当前java调用者
注意该函数被extern "C"包围着,是为了告诉C++编译器编译时采用C风格的函数命名协议,而不是C++风格的函数命名协议。因为C++为了支持函数重载,编译时采用一种叫做mangling的方式为每一个重载函数命命名。详细信息可以参见我的另一篇文章C/C++拾遗之extern “C”

该头文件中引用了一个java的头文件jni.h,该头文件所在目录为

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值