IntelliJ IDEA平台下JNI编程全解

  

作者:章华燕

编辑:陈人和

        

前  言

众所周知,Java语言是基于虚拟机的解释性语言(Java代码经过编译器编译之后并不是能够直接在机器上执行的二进制代码,而是JVM虚拟机能够识别的字节码,依靠Java虚拟机进行解释执行)。而C/C++是编译型语言(编译完成后是能够直接在机器上运行的二进制指令)。虽然,随着Java虚拟机技术的改善和优化,Java性能相对于刚出来那会已经有了极大地提升,但是C/C++语言的性能还是会比Java要高,这是不争的事实。并且我们知道,现在很多服务程序都是Java程序编写的,但是有时候,对于服务的某些对性能要求非常高的地方我们希望用C/C++来编写,以满足程序的性能要求。这时候,我们就需要用到JNI技术,通过它Java可以调用C/C++编写的程序。

01

搭建gcc编译环境

JNI既然是使用Java调用C/C++程序,那么我们首先得有一个C/C++编译环境:将C/C++代码编译成相关平台可执行的动态链接库(Windows下的.dll、Linux下的.so、Mac下的.dylib等)。因为我使用的是Mac,因此本文主要以Mac为例进行进行介绍,但是我也会对其它两个平台的方法也会进行介绍。

Linux和Mac电脑一般都会自带gcc编译器,直接在命令行中输入gcc --version就可以查看gcc版本号。如果读者使用的是Windows平台,那么我建议使用MinGW,从相关网站把需要的MinGW下载并将相关库和程序解压到指定目录,假设是D:MinGw。解压完成后,刚才指定的解压目录中的bin加入到path环境变量中。例如上面图中解压到D:\MinGw,那么应当将D:\MinGw\bin加入到环境变量path中。注意,请确保bin目录确实在D:\MinGw中,如果不在,可能在更深一层目录中,自行确定bin的目录。此时,你也可以打开控制台,输入:gcc -v 查看

02

编写jva代码

在IntelliJ IDEA中创建一个Java项目,新建一个类:JNIDemo.java,并编写如下所示代码:

IntelliJ IDEA平台下JNI编程全解_第1张图片

函数System.loadLibrary()是加载dll(windows)或so(Linux)库,只需名称即可,无需加入文件名后缀(.dll或.so)。native关键字将函数sayHello()声明为本地函数,由C/C++实现。具体的实现就在JNIDemo.dll (Windows平台)、libJNIDemo…so(Linux平台)、libJNIDemo.dylib(Mac)。

03

一键生成头文件

虽然可以手动通过命令生成头文件,但是我觉得比较麻烦,这里我们使用IDEA进行一键生成,依次点击File > Settings > Tools > External Tools:  

IntelliJ IDEA平台下JNI编程全解_第2张图片

添加一个先的External Tools:

IntelliJ IDEA平台下JNI编程全解_第3张图片

在JNIDemo.java文件中 点击右键 > External Tools > Generate Header File:

IntelliJ IDEA平台下JNI编程全解_第4张图片

 这是项目目录下的的jni目录下就生成了一个 JNIDemo.h ,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class JNIDemo */


#ifndef _Included_JNIDemo
#define _Included_JNIDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JNIDemo
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JNIDemo_sayHello
  (JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif
#endif

04

编写C程序并一键生成dll(so或dylib)

接下来我们在jni目录下再创建一个 JNIDemo.c ,内容如下:

#include "jni.h"
#include 
#include "JNIDemo.h"


JNIEXPORT void JNICALL Java_JNIDemo_sayHello (JNIEnv * env, jobject thisObj){
    printf("Hello World!\n");
    return;
}

接下来干嘛?你猜……

按照前面的方法,点击 File > Settings > Tools > External Tools > +,输入内容如下:

  • Windows版

Generate DLL

-Wl,--add-stdcall-alias -I"$JDKPath$\include" -I"$JDKPath$\include\win32" -shared -o ./lib/$FileNameWithoutExtension$.dll ./jni/$FileNameWithoutExtension$.c
$ProjectFileDir$
  • Mac版

Generate DLL

-dynamiclib -I"$JDKPath$/include" -I"$JDKPath$/include/darwin" -shared -o ./lib$FileNameWithoutExtension$.dylib ./jni/$FileNameWithoutExtension$.c
$ProjectFileDir$

IntelliJ IDEA平台下JNI编程全解_第5张图片

在HelloJNI.c中点击右键,选择External Tools>Generate DLL。此时,在项目目录中会得到dll文件(别忘了我的是Mac):

IntelliJ IDEA平台下JNI编程全解_第6张图片

05

运行JNIDemo.java

至此,大功告成,运行结果如下:

IntelliJ IDEA平台下JNI编程全解_第7张图片

当然,这只是一个最简单的JNI调用,真正项目中需要使用的JNI程序往往是需要Java与C/C++之间进行大量的数据传递。Java与C/C++中的数据传递并不是那么简单的事情,毕竟不同的语言的基本类型都不是完全一样,因此需要严格地按照相关的约定,当然这是我即将在新的篇章中进行详细介绍的。

 

END

往期回顾

特定场景下Yolo改进算法:Poly-Yolo

万物皆Embedding,从经典的word2vec到深度学习基本操作item2vec

机器学习论文笔记—如何利用高效的搜索算法来搜索网络的拓扑结构

强化学习(二)马尔科夫决策过程(MDP)

机器学习算法工程师


                                            一个用心的公众号


 

你可能感兴趣的:(IntelliJ IDEA平台下JNI编程全解)