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

运行结果:

相关推荐
_李小白7 分钟前
【C++学习笔记】新特性之inline变量
c++·笔记·学习
罗超驿26 分钟前
22.深入剖析JDBC架构:从原生API到企业级数据交互核心
java·数据库·mysql·面试
一直有一个ac的梦想35 分钟前
cmu15445 2025fall lec 18 transactions with two-phase lock
java·开发语言·数据库
九皇叔叔36 分钟前
Spring-Ai-Alibaba [04] 04-llm-platform-custom-demo
java·人工智能·spring
技术路上的探险家38 分钟前
Sa-Token 单点登录(SSO)三种模式大白话详解:告别重复登录
java·sa-token·单点登录·sso
JAVA社区1 小时前
Java进阶全套教程(四)—— SpringMVC框架详解
java·开发语言·spring·面试·职场和发展
ㄣ知冷煖★1 小时前
统一网关架构实践:从 Token 鉴权到路由、策略与凭证池转发全链路解析
java·服务器·架构
Lumbrologist1 小时前
【C++】零基础入门 · 第 2 节:变量、基本数据类型与输入输出
java·开发语言·c++
GISer_Jing1 小时前
Three.JS渲染架构解读
java·javascript·架构
绝知此事1 小时前
Netty实战:从零构建高性能TCP通信服务(含心跳检测)
java·网络·spring boot·网络协议·tcp/ip