文章目录
- 1_JNI是什么?
- 2_使用
- 3_扩展
1_JNI是什么?
JNI 是Java Native Interface
的缩写,通过JNI,允许Java代码与其他语言(通常是C或C++)编写的本地应用程序或库进行交互。简而言之就是,Java可以通过JNI调用C 或 C++ 语言写的代码。
2_使用
1、首先,准备一个demo
让我们进行JNI的快速入门使用:
/**
* @author shenyang
* @version 1.0
* @info JNI
* @since 2024/6/29 下午5:03
*/
public class JNIDemo {
public static void main(String[] args) {
System.out.println(System.getProperty("java.library.path"));
System.out.println(add(1,2));
}
}
2、需要将C/C++实现的方法用native
关键字声明。
- 由
native
关键字声明的方法我们就不需要给出方法体了,直接给出声明就好了。
public static native int add(int a, int b);//这个方法的作用是将两个整型相加
3、加载动态链接库(windows
上.dll
为后缀,linux上.so
为后缀名),通常是使用静态代码块来进行导入。
- 使用 System对象的
public static void loadLibrary(String libname)
方法不需要后缀,只要(库所在路径加上)库名。
static {
System.loadLibrary("jniDemo");
}
4、使用 javac -h
或 javah
生成.h
为后缀的头文件
- 注意:jdk10之后将
javah
这一命令移除了,JEP313: 移除JDK中附带的javah工具。 - 注意下面第一个参数是存放到当前路径下(
./
)
javac -h ./ JNIDemo.java
- 生成的头文件
JNIDemo.h
。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h> //这个头文件在jdk/include/下
/* Header for class JNIDemo */
#ifndef _Included_JNIDemo
#define _Included_JNIDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JNIDemo 说明这个方法是在哪个类里
* Method: add 对应的是java中的add方法
* Signature: (II)I 括号里两个II表示第一个参数和第二个参数都是int类型,括号后面的I表示这个方法的返回值是int类型
* 下面这部分是C++需要实现的函数声明
*/
JNIEXPORT jint JNICALL Java_JNIDemo_add
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
下面这部分是C++需要实现的函数声明:
JNIEXPORT jint JNICALL Java_JNIDemo_add
(JNIEnv *, jclass, jint, jint);
5、根据生成的头文件里的函数声明实现对应的函数,创建JNIDemo.cpp
文件。
- 注意:下面的代码包含了之前生成的头文件
JNIDemo.h
,还需要其他头文件也可以一并包含进去,比如:iostream
。 - 下面四个参数:
JNIEnv *
是一个指针封装了一些JNI
的操作在里面,jclass
参数也用不到只放一个参数类型就行了,后面两个参数因为用的到所以把参数名加上。 - 函数的最终目的是返回
a+b
,再加上一些其他操作我们进行测试;
#include "JNIDemo.h"
#include <iostream>
JNIEXPORT jint JNICALL Java_JNIDemo_add(JNIEnv *, jclass , jint a, jint b)
{
std::cout <<"a = "<< a<<" b= "<< b <<std::endl;
return a+b;
}
6、将上面的cpp文件编译成动态链接库。
给对C++不太了解的同学解释下下面命令的意义:
-
-o jniDemo.dll
: 指定输出文件的名称为jniDemo.dll
(与System.loadLibrary("jniDemo")
中保持统一)。在Windows系统上,动态链接库通常以.dll
为扩展名。 -
-fPIC
: 表示生成位置无关代码(Position-Independent Code)。这是生成共享库时常用的选项,使得生成的代码在加载到内存中的任何位置时都可以正确运行。 -
-shared
: 指定生成一个共享库(动态链接库),而不是可执行文件。 -
-I
: 包含路径选项,用于指定头文件所在目录。在这里,包含了特定于Windows系统的Java头文件。 -
JNIDemo.cpp
: 源文件名,包含了具体的JNI方法实现。 -
如果
windows
电脑上使用不了g++
命令,那么可以下载MinGWX64 - x86_64-win32-sjlj。
g++ -o jniDemo.dll -fPIC -shared -I"E:\shenyang\.jdks\jdk-1.8\include\win32" -I"E:\shenyang\.jdks\jdk-1.8\include" JNIDemo.cpp
执行完毕后发先目录下出现jniDemo.dll
文件:
最后运行 JNIDemo.java
,查看运行结果:
3_扩展
基础数据类型对应表:
Java 类型 | JNI 类型 | C/C++ 类型 | 描述 |
---|---|---|---|
boolean | jboolean | unsigned char | 布尔类型,值为true 或false ,使用0表示false ,非0表示true 。 |
byte | jbyte | signed char | 8位有符号整数 |
char | jchar | unsigned short | 16位无符号Unicode字符 |
short | jshort | short | 16位有符号整数 |
int | jint | int | 32位有符号整数 |
long | jlong | long long | 64位有符号整数 |
float | jfloat | float | 32位单精度浮点数 |
double | jdouble | double | 64位双精度浮点数 |
void | void | void | 无类型 |
引用数据类型对应表:
Java 类型 | JNI 类型 | 描述 |
---|---|---|
String | jstring | Java字符串 |
Object | jobject | 任意Java对象 |
Class | jclass | Java类 |
Throwable | jthrowable | Java异常对象 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyteArray | 字节型数组 |
char[] | jcharArray | 字符型数组 |
short[] | jshortArray | 短整型数组 |
int[] | jintArray | 整型数组 |
long[] | jlongArray | 长整型数组 |
float[] | jfloatArray | 单精度浮点型数组 |
double[] | jdoubleArray | 双精度浮点型数组 |
任意类型的对象数组 | jobjectArray | 对象数组 |
Java数组中的任意类型 | jarray | 通用数组类型 |