java jni demo

简介

JNI是Java Native Interface的英文缩写, 中文翻译为本地调用, 自从Java 1.1开始就成为了Java标准的一部分.

C/C++是系统级的编程语言, 可以用来开发任何和系统相关的程序和类库, 但是Java本身编写底层的应用比较难实现, 使用JNI可以调用现有的本地库, 极大地灵活了Java的开发.

C/C++的效率是目前最好的语言, 可以使用C/C++来实现一些实时性非常高的部分. C/C++和Java本身都是非常流行的编程语言, 一些大型软件中经常使用语言之间的混合编程

新建一个HelloJNI类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.jianganwei.demo;

/**
* @program: Bemoan
* @description: JNI
* @author: jianganwei
* @create: 2018-11-26 14:46
**/
public class HelloJNI {
static{
System.out.println(System.getProperty("java.library.path"));
System.loadLibrary("HelloJNI");
}
private native void sayHello();

public static void main(String[] args) {

new HelloJNI().sayHello();
}

}

代码的静态代码块在这个类被类加载器加载的时候调用了System.loadLibrary()方法来加载一个native库“HelloJNI”(这个库中实现了sayHello函数)。这个库在windows品台上对应了“helloJNI.dll”,而在类UNIX平台上对应了“libhelloJNI.so”。这个库应该包含在Java的库路径(使用java.library.path系统变量表示)上,否则这个上面的程序会抛出UnsatisfiedLinkError错误。你应该使用VM的参数-Djava.library.path=path_to_lib来指定包含native库的路径。
接下来,我们使用native关键字将sayHello()方法声明为本地实例方法,这就很明显地告诉JVM:这个方法实现在另外一个语言中(C/C++),请去那里寻找他的实现。注意,一个native方法不包含方法体,只有声明。上面代码中的main方法实例化了一个HelloJJNI类的实例,然后调用了本地方法sayHello()。

编译得到.class文件

javac HelloJNI.java 获得build一下项目.class 文件 就在target/classes中

链接生成头文件

1
javah -classpath target/classes -d ./jni com.jianganwei.demo.HelloJNI

会在./jni 这个目录下生成 jni/com_jianganwei_demo_HelloJNI.h 文件内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <jni.h>
/* Header for class com_jianganwei_demo_HelloJNI */

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

#ifdef __cplusplus
}
#endif
#endif

在idea中配置一键生成头文件 5bfe364aabd0e

编写c或c++代码c为.c c++为cpp文件

新建文件.c或.cpp文件,实现上一步头文件的接口

1
2
3
4
5
6
7
8
#include<jni.h>
#include <stdio.h>
#include "com_jianganwei_demo_HelloJNI.h"

JNIEXPORT void JNICALL Java_com_jianganwei_demo_HelloJNI_sayHello(JNIEnv *env, jobject thisObj){
printf("hello world!\n");
return;
}

生成.o

1
2

gcc -fPIC -c -I"/opt/jdk1.8/jdk1.8.0_151/include" -I"/opt/jdk1.8/jdk1.8.0_151/include/linux" jni/HelloJNI.c

上面是jdk的路径,window 下第2个路径有点不同进去jdk 目录看一下就好了

生成.so文件,win 为dll
1
gcc -shared HelloJNI.o -o libHello.so
最后把生成的so文件放到java.library.path

把so 文件放到某个目录下,或者配置运行时环境 -Djava.library.path=/home/jianganwei/IdeaProjects/Bemoan/lib 到so文件所在目录

最后

生成o 和so 文件可以合成一步

1
gcc -fPIC -I"/opt/jdk1.8/jdk1.8.0_151/include" -I"/opt/jdk1.8/jdk1.8.0_151/include/linux" -shared -o ./lib/libHelloJNI.so  jni/HelloJNI.c

idea 配置一键生成

5bfe3b194b4d5