JNI 初探
JNI 简介
JNI 是** Java Native Interface **的缩写,它提供了若干的 API 实现了 Java 和其他语言的通信(主要是 C&C++)。从 Java1.1 开始,JNI 标准成为 java 平台的一部分,它允许 Java 代码和其他语言写的代码进行交互。JNI 一开始是为了本地已编译语言,尤其是 C 和 C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用 java 与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI 标准至少要保证本地代码能工作在任何 Java 虚拟机环境。
相信大家在看源码的时候都看见过用** native **修饰的方法,这些方法就是用 C/C++语言实现的,那到底 java 是如何调用的这些方法的呢?
上手
准备工作
文中环境为 Linux 下 Centos6 版本
✅ 首先需要有JDK
(我的是 jdk1.7),编译 java
✅ 然后需要gcc
用来编译 C/C++
Java 代码
public class JniTest {
public static void main(String[] args) {
new JniTest().hi();
}
static {
//加载一个动态链接库
System.loadLibrary("jniTest");
}
private native void hi();
}
在静态代码块里面加载了一个 动态链接库
编写完之后直接javac JniTest.java
编译一下,然后执行javah -jni JniTest
,会在当前目录下生成一个JniTest.h
的头文件如下
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JniTest */
#ifndef _Included_JniTest
#define _Included_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JniTest
* Method: hi
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JniTest_hi
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
C 代码
#include<stdio.h>
#include "JniTest.h"
#include <jni.h>
//这一段来自上面的头文件
JNIEXPORT void JNICALL Java_JniTest_hi
(JNIEnv *env, jobject o){
printf("you successfully called the c code\n");
}
JNIEnv*
:用于引用 JNI 环境,该指针变量可以访问所有 JNI 函数jobject
:引用this
Java 对象,也就是可以用来访问当前 java 调用者
写完之后执行如下命令编译它
gcc -fPIC -D_REENTRANT -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -c JniTest.c
会在当前目录下生成一个JniTest.o
的可执行文件。
然后执行
gcc -shared JniTest.o -o libjniTest.so
注意linux
上动态链接库必须以lib
开头,所以这里是libjniTest
后面的是前面java
代码中加载的哪个动态链接库名称jniTest
,最后会在当前目录下生成一个libjniTest.so
的动态库
执行
首先给libjniTest.so
赋予可执行权限
chmod 777 libjniTest.so
因为我这里没有设置java.library.path
所以需要在运行的时候加上路径
java -Djava.library.path=/usr/jnitest JniTest
结果
篇文章中只是简单的调用了 C 语言的代码,关于如何传递参数,如何返回值,后面遇到之再做记录