初识JNI

JNI概念

JNI (Java Native Interface) 是 Java 平台的一个关键组件,它允许 Java 代码调用本地应用程序或库中的函数(通常是 C 或 C++ 代码),同时也允许本地代码调用 Java 方法。JNI 为 Java 和本地代码之间的交互提供了一个桥梁,使得开发者可以在 Java 应用程序中利用本地代码的强大功能,例如高性能计算、设备驱动程序访问等。

JNI 的用途

  • 性能优化:对于计算密集型任务,使用 C 或 C++ 编写的本地代码通常比纯 Java 代码更快。
  • 硬件访问:有些硬件设备只能通过本地代码访问,JNI 提供了一种途径来实现这种访问。
  • 跨语言集成:JNI 使得 Java 代码可以调用其他语言编写的库,反之亦然。

JNI 的工作流程

1.编写java测试类

2.利用java测试类生成C头文件

3.利用C头文件编写C代码

4.生成C库

5.java调用测试

第一步:编写java测试类

没有java基础,在ubuntu下用java相关命令简单写了个类,以下附有代码和执行命令。

代码如下:

java 复制代码
package com.aijiao.test;
public class JNIDemo {
	//定义一个方法,该方法在C中实现
	public native String testHello();
	            
	public static void main(String[] args){
		//加载C文件
		System.loadLibrary("TestJNI2");
	    JNIDemo jniDemo = new JNIDemo();
		System.out.println(jniDemo.testHello());
	}
}

第二步:利用java测试类生成C头文件

生成命令如下:

复制代码
javah -classpath . -jni com.aijiao.test.JNIDemo

该命令需要在java测试类的工程的bin目录下执行,这里没有新建工程,不存在bin目录,用javah执行总是出错,最后照着别人生成的头文件改了下,发现也可以用,头文件大致长这样:

java 复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_aijiao_test_JNIDemo */

//避免重复包含头文件

#ifndef _Included_com_aijiao_test_JNIDemo
#define _Included_com_aijiao_test_JNIDemo

//c++编译环境中才会定义__cplusplus (plus就是"+"的意思

#ifdef __cplusplus
extern "C" {  //告诉编译器下面的函数是c语言函数(因为c++和c语言对函数的编译转换不一样,主要是c++中存在重载)
#endif
/*
 * Class:     com_aijiao_test_JNIDemo
 * Method:    displayHelloJni
 * Signature: ()V
 */
JNIEXPORT jstring JNICALL Java_com_aijiao_test_JNIDemo_testHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

其实这个头文件不是必须的

第三步:利用C头文件编写C代码

有用javah生成头文件对应的c代码

cpp 复制代码
#include "com_aijiao_test_JNIDemo.h"
#include <iostream>
#include <stdio.h>

JNIEXPORT jstring JNICALL Java_com_aijiao_test_JNIDemo_testHello
(JNIEnv * env, jobject obj) {
	    //printf("this is C++ print");
	    return env->NewStringUTF("set value success");
}

没有用javah生成头文件对应的c代码

cpp 复制代码
#include "jni.h"
#include <iostream>
#include <stdio.h>

extern "C"
JNIEXPORT jstring JNICALL Java_com_aijiao_test_JNIDemo_testHello
(JNIEnv * env, jobject obj) {
	    //printf("this is C++ print");
	    return env->NewStringUTF("set value success");
}

两个略有差异,主要是要把extern "C"带上,不然会链接不到函数

第四步:生成C库

先拷贝两个头文件(jni.h和jni_md.h)过来再生成.so文件。jni.h和jni_md.h都在jdk目录下有,直接用find命令找需要拷贝到cpp文件夹下

g++ TestJNI.cpp -fPIC -shared -o libTestJNI2.so

第五步:java调用测试

整个测试工程文件层级如下:

以下java命令都是在java文件夹下执行的:

根据.java文件生成.class文件:javac -d . JNIDemo.java

执行class文件:java com.aijiao.test.JNIDemo

指定libTestJNI2.so文件的路径,把.so路径加入环境变量:export LD_LIBRARY_PATH=/home/lxj/myproject/testJNI2/cpp:$LD_LIBRARY_PATH,不然会加载不上库会报错

参考菜鸟教程:JNI 入门教程 | 菜鸟教程 (runoob.com),也有自己踩得坑,欢迎大家评论,有交流才会有进步

相关推荐
郝学胜-神的一滴4 分钟前
力扣 144:二叉树前序遍历的优雅实现
java·数据结构·c++·python·算法·leetcode·职场和发展
摇滚侠5 分钟前
CSDN AI 数字营销测评 专家标注
java
长河7 分钟前
APISIX
java·网络
go不是csgo8 分钟前
Go-GMP-调度器深度解析(改进版本)
java·linux·golang
轮子飞了8 分钟前
基于 Spring AI + Milvus 的 RAG 混合检索实战
java
Evand J9 分钟前
【MATLAB程序】基于σ修正自适应律的多无人机菱形编队控制仿真,附下载链接
开发语言·matlab·无人机·控制·编队飞行·多uav
risc1234569 分钟前
【Lucene】理解不是看见光,而是让眼睛适应黑暗
java·开发语言
枕星而眠10 分钟前
C++面向对象核心:类间关系与继承深度解析
运维·开发语言·c++·后端
小谢小哥10 分钟前
62-Maven核心详解
java·后端·架构
秋越10 分钟前
从工程角度理解嵌入式C语言关键字
c语言·开发语言·嵌入式·嵌入式软件开发·嵌入式c语言·c语言关键字