IntelliJ IDEA平台下JNI编程全解

Posted JeemyJohn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IntelliJ IDEA平台下JNI编程全解相关的知识,希望对你有一定的参考价值。

文章目录

1、前言

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

2、搭建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 查看

3、编写Java代码

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

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

4、一键生成头文件

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

添加一个先的External Tools:

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


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

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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

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

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

#include "jni.h"
#include <stdio.h>
#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
<GCC路径>
-Wl,--add-stdcall-alias -I"$JDKPath$\\include" -I"$JDKPath$\\include\\win32" -shared -o ./lib/$FileNameWithoutExtension$.dll ./jni/$FileNameWithoutExtension$.c
$ProjectFileDir$
  • Mac版
Generate DLL
<GCC路径>
-dynamiclib -I"$JDKPath$/include" -I"$JDKPath$/include/darwin" -shared -o ./lib$FileNameWithoutExtension$.dylib ./jni/$FileNameWithoutExtension$.c
$ProjectFileDir$


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

6、运行JNIDemo.java

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

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

以上是关于IntelliJ IDEA平台下JNI编程全解的主要内容,如果未能解决你的问题,请参考以下文章

IntelliJ IDEA平台下JNI编程全解

IntelliJ IDEA平台下JNI编程—HelloWorld篇

IntelliJ IDEA平台下JNI编程—HelloWorld篇

IntelliJ IDEA平台下JNI编程—类型映射

IntelliJ IDEA平台下JNI编程—字符串数组

IntelliJ IDEA平台下JNI编程—本地C代码访问JAVA对象