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);
	}
}

运行结果:

相关推荐
忧郁的Mr.Li1 天前
SpringBoot中实现多数据源配置
java·spring boot·后端
yq1982043011561 天前
静思书屋:基于Java Web技术栈构建高性能图书信息平台实践
java·开发语言·前端
一个public的class1 天前
你在浏览器输入一个网址,到底发生了什么?
java·开发语言·javascript
有位神秘人1 天前
kotlin与Java中的单例模式总结
java·单例模式·kotlin
golang学习记1 天前
IntelliJ IDEA 2025.3 重磅发布:K2 模式全面接管 Kotlin —— 告别 K1,性能飙升 40%!
java·kotlin·intellij-idea
爬山算法1 天前
Hibernate(89)如何在压力测试中使用Hibernate?
java·压力测试·hibernate
消失的旧时光-19431 天前
第十四课:Redis 在后端到底扮演什么角色?——缓存模型全景图
java·redis·缓存
BD_Marathon1 天前
设计模式——依赖倒转原则
java·开发语言·设计模式
BD_Marathon1 天前
设计模式——里氏替换原则
java·设计模式·里氏替换原则
Coder_Boy_1 天前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring