初识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),也有自己踩得坑,欢迎大家评论,有交流才会有进步

相关推荐
阿猿收手吧!7 小时前
【C++】string_view:高效字符串处理指南
开发语言·c++
风生u7 小时前
activiti7 详解
java
玄同7657 小时前
我的 Trae Skill 实践|使用 UV 工具一键搭建 Python 项目开发环境
开发语言·人工智能·python·langchain·uv·trae·vibe coding
岁岁种桃花儿7 小时前
SpringCloud从入门到上天:Nacos做微服务注册中心(二)
java·spring cloud·微服务
Word码7 小时前
[C++语法] 继承 (用法详解)
java·jvm·c++
Yorlen_Zhang7 小时前
Python Tkinter Text 控件完全指南:从基础编辑器到富文本应用
开发语言·python·c#
lxl13077 小时前
C++算法(1)双指针
开发语言·c++
TT哇7 小时前
【实习 】银行经理端两个核心功能的开发与修复(银行经理绑定逻辑修复和线下领取扫码功能开发)
java·vue.js
逝水如流年轻往返染尘7 小时前
Java中的数组
java
不绝1918 小时前
C#进阶:预处理指令/反射,Gettype,Typeof/关键类
开发语言·c#