JNI简单学习(java调用C/C++)

JNI

JNI(Java Native Interface)是 JDK 内置的标准原生接口,是 Java 平台与 C/C++ 等原生代码(Native Code)交互的底层规范,允许 Java 虚拟机(JVM)中的 Java 代码调用原生代码,也支持原生代码回调 Java 代码。与 JNA(基于 JNI 封装的上层类库)不同,JNI 是 Java 与原生代码通信的 "底层基础",所有 Java 调用原生库的方案(包括 JNA、JNR 等)最终都基于 JNI 实现。

核心组件

组件 作用
jni.h 核心头文件,定义 JNI 的类型、函数、宏(如JNIEnv、jobject、FindClass);
JNIEnv* 核心指针,提供 JNI 函数调用接口(如创建 Java 对象、调用 Java 方法、类型转换),线程私有;
JavaVM* Java 虚拟机实例指针,用于跨线程 / 跨进程获取JNIEnv,全局唯一;

关键类型映射(Java 对应 C/C++)

Java 类型 JNI 类型 C/C++ 类型
byte jbyte signed char
short jshort short
int jint int
long jlong long long(8 字节)
float jfloat float
double jdouble double
boolean jboolean unsigned char
char jchar unsigned short
String jstring 无直接映射(需通过 JNI 函数转换为 char*)
Object jobject 无直接映射(指向 Java 对象的指针)
数组 jarray/ jintArray/ jbyteArray 对应数组类型指针

演示

演示环境:

开发环境为:idea、visual studio

java版本:jdk-17.0.15

c++:ISO C++14 标准 (/std:c++14)

x64环境下

1.创建Java 类

创建一个名为JavaCode的maven项目

声明native方法

python 复制代码
public class NativeFunction 
{
	public native int add(int a, int b);
}

2.生成 JNI 头文件

通过Java 命令行生成包含方法签名的 C/C++ 头文件;

复制代码
javac -h jni NativeFunction.java

执行完以上命令后,会生成一个jni文件夹,里面的org_example_NativeFunction.h文件就是c/c++的头文件

3.编写 C/C++ 实现

创建一个名为CPPCode的空项目

将生成的头文件(org_example_NativeFunction.h)移动到头文件夹下

此时头文件(org_example_NativeFunction.h)里面会报错,在windows环境中需要引入2个头文件,分别为:

复制代码
jni.h
jni_md.h

这两个文件在java文件夹里面,比如下面这两个路径:

复制代码
D:\Program Files (x86)\java\jdk-17.0.15\include
D:\Program Files (x86)\java\jdk-17.0.15\include\win32

点击项目属性,将上面2个路径放进附加包含目录里面

补充:如果没有C/C++选项有可能是没创建C/C++文件导致的,创建了就好了(提前创建NativeFunction.cpp文件)

实现头文件(org_example_NativeFunction.h)中声明的原生方法

创建NativeFunction.cpp文件

cpp 复制代码
//引入头文件
#include "org_example_NativeFunction.h"

//实现方法,将需要使用的参数设置名称a,b
JNIEXPORT jint JNICALL Java_org_example_NativeFunction_add(JNIEnv*, jobject, jint a, jint b)
{
	return a + b;
}

4.编译动态库

根据自己的平台配置

项目属性设置为:

配置类型设置为:动态库

生成解决方案:

我的是x64环境

然后点击生成解决方案

在项目的 \x64\Debug 目录下会生成ddl文件

5.Java加载动态库

将编译好的dll动态库放进资源文件夹下:

编写加载动态库的代码,Java 加载动态库并调用 native 方法。

java 复制代码
public class Main 
{
	static 
	{
		//加载动态库
		String dllPath = System.getProperty("user.dir")+"\\src\\main\\resources\\CPPCode.dll";
		//不支持classpath
		System.load(dllPath);
	}
	
	public static void main(String[] args) 
	{
		//创建NativeFunction对象
		NativeFunction nativeFunction = new NativeFunction();
		//调用add方法
		int result = nativeFunction.add(5, 6);
		System.out.println("add(5, 6) = "+result);
	}
}

运行结果:

相关推荐
学到头秃的suhian2 小时前
Springboot进阶知识
java·spring boot·spring
期待のcode2 小时前
Thymeleaf模板引擎
java·html·springboot
吃西瓜的年年2 小时前
3. C语言核心语法2
c语言·嵌入式硬件·改行学it
白宇横流学长2 小时前
基于SpringBoot实现的电子发票管理系统
java·spring boot·后端
白宇横流学长2 小时前
基于SpringBoot实现的智慧就业管理系统
java·spring boot·后端
TL滕2 小时前
从0开始学算法——第十二天(KMP算法练习)
笔记·学习·算法
weixin_462446232 小时前
EasyExcel 动态修改模板 Sheet 名称:自定义 SheetWriteHandler 拦截器
java·开发语言·easyexcel
赵庆明老师2 小时前
NET 使用SmtpClient 发送邮件
java·服务器·前端
苏小瀚2 小时前
[Java EE] HTML·CSS·JavaScript基础
java·java-ee