初识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 分钟前
【Java数据结构】链表相关的算法
java·数据结构·链表
爱编程的小新☆8 分钟前
不良人系列-复兴数据结构(二叉树)
java·数据结构·学习·二叉树
m0_7482478011 分钟前
SpringBoot集成Flowable
java·spring boot·后端
小娄写码21 分钟前
线程池原理
java·开发语言·jvm
m0_6305206422 分钟前
Python初识
开发语言·python
网安-轩逸3 小时前
IPv4地址表示法详解
开发语言·php
陌上花开࿈5 小时前
调用第三方接口
java
Aileen_0v05 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
西猫雷婶7 小时前
python学opencv|读取图像(十九)使用cv2.rectangle()绘制矩形
开发语言·python·opencv
桂月二二7 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes