后端 | Java利用JNI调用C++(dll/so)函数

Java利用JNI调用C++(dll/so)函数


  JNI(Java Native Interface ,Java本地接口),使用JNI规范可以与其它语言程序进行交互,调用本地方法、访问本地资源,从而扩展Java的功能。

  • 通过JNI调用本地代码,利用本地代码的高效性和底层功能来完成特定任务,譬如:使用C来控制Nginx、设置开机启动。
  • 通过JNI可以访问本地系统资源,如文件、网络接口等。使得Java程序可以直接与本地环境进行交互,实现更加灵活和强大的功能。

1 JNI操作步骤

  1. 创建Java本地方法

    • 在Java代码中,通过native关键字声明一个本地方法
  2. 生成Java本地接口

    • 使用Java的javah命令,根据Java类文件生成对应的本地接口文件
  3. 实现Java本地接口

    • 使用Visual Studio将本地代码编译成动态库
  4. 加载并调用dll文件中的方法

    • 加载System.loadLibrary("libname")或者System.load("path")
    • 调用本地方法

2 实现

2.1 创建本地方法
arduino 复制代码
package cn.chao.datamsg;
​
public class DataMsgFormatTest {
    static {
        System.loadLibrary("DataMsgFormat");
    }
 
    public native String version();
 
    public native String base64(String plain);
 
    public static void main(String[] args) {
        new DataMsgFormatTest().version();
    }
 
}
2.2 生成Java本地接口
复制代码
javah -encoding utf-8 -classpath . -jni cn.chao.datamsg.DataMsgFormatTest
arduino 复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_chao_datamsg_DataMsgFormatTest */
​
#ifndef _Included_cn_chao_datamsg_DataMsgFormatTest
#define _Included_cn_chao_datamsg_DataMsgFormatTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_chao_datamsg_DataMsgFormatTest
 * Method:    version
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_version
  (JNIEnv *, jobject);
​
/*
 * Class:     cn_chao_datamsg_DataMsgFormatTest
 * Method:    base64
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_base64
  (JNIEnv *, jobject, jstring);
​
#ifdef __cplusplus
}
#endif
#endif
  • JNIEXPORTJNICALLJNI宏,用于导出JNI函数

  • Java_cn_chao_datamsg_DataMsgFormatTest_version是Java本地方法的名称

    • cn_chao_datamsg是类路径
    • DataMsgFormatTest是类名
    • version是方法名
    • 可以使用JNIEnvjobject参数来访问Java虚拟机和对象
    • jstring是JNI类型,表示Java的String类型
3 实现Java本地接口

使用的是Visual Studio 2010 专业版以及Win7系统

  • 新建项目Win32项目的空项目
  • 创建的项目目录
  • 头文件文件夹中,引入 《2.2 生成Java本地接口》 生成的.h文件
  • 还需要引入包目录,为jdk/includejdk/include/win32
  • 编写实现函数cpp文件
c 复制代码
#include <iostream>
#include <string.h>
#include <jni.h>
​
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     cn_chao_datamsg_DataMsgFormatTest
 * Method:    version
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_version
  (JNIEnv * env, jobject obj){
      std::string data_msg_version = "1.0.0";
      return env->NewStringUTF(data_msg_version.c_str());
}
​
/*
 * Class:     cn_chao_datamsg_DataMsgFormatTest
 * Method:    base64
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_cn_chao_datamsg_DataMsgFormatTest_base64
  (JNIEnv * env, jobject obj, jstring str){
      std::string data_msg_version = "1.0.0";
      return env->NewStringUTF(data_msg_version.c_str());
}
​
#ifdef __cplusplus
}
#endif
  • 生成64位和32位dll文件
4 测试Java调用接口
  • System.load("/proc/DataMsgFormat.dll")
  • System.loadLibrary("DataMsgFormat");
相关推荐
梓䈑几秒前
【动态规划系列】路径问题、子数组 和 子序列问题、背包问题
c++·算法·动态规划
考虑考虑2 分钟前
elasticSearch中的element_type
运维·后端·elasticsearch
aqiu1111114 分钟前
【数位 DP / 记忆化搜索】蓝桥云课 - 光轨区的 AI 数 题解
c++·算法·蓝桥杯·数位dp
CodeStats6 分钟前
【Java类加载器】Java 类加载器完整体系深度拆解(下):自定义加载器实战与 SPI 破坏双亲委派(MySQL 驱动揭秘)
java·开发语言·jvm·classloader·双亲委派
dishugj9 分钟前
操作系统四大特征|软考架构师考点梳理
java·linux·服务器
砚底藏山河18 分钟前
并发与限频工程:把20只的2秒压到0.5秒不封号(魔码量化实战 #03)
java·开发语言·数据库·python·金融
ly768919 分钟前
Spring WebFlux背压机制在生产环境的调优与陷阱
java·spring·microsoft·webflux·project reactor·背压·响应式流
掘金者阿豪26 分钟前
飞牛部署 Wallos:把长期订阅和周期支出放进自己的 NAS 管理
后端
欧特克_Glodon29 分钟前
OpenCV计算机视觉开发入门与实践<三十七>:OpenCV中的机器学习
c++·opencv·机器学习·计算机视觉
云雀衔光31 分钟前
MCP 协议全景:为什么它是 AI 连接工具的「USB-C」
java·开发语言·数据库·人工智能·ai编程