Java中调用由C/C++实现的本地库(JNI本地程序调用)

文章目录

  • 背景
  • 介绍
    • 什么是JNI?
    • 什么是本地库?
    • 开发Java使用JNI本地库步骤
  • 编写Java类实现JNI本地调用
    • windows系统下编译动态链接库
      • 创建Java项目(demo)
        • 第一步:编写带有native的Java类
        • 第二步:javac生成`NativeDemo`类的字节码文件
        • 第三步:javah根据字节码文件生成jni头文件(NativeDemo.h)
      • 创建C++动态链接库(DLL)
        • 第一步:打开Microsoft Visual Studio 2022创建项目
        • 第二步:配置项目并创建
        • 第三步:加载javah生成的NativeDemo.h头文件
        • 第四步:配置jni.h导入找不到问题
        • 第五步:编辑源码,导入`NativeDemo.h`头,实现对应方法。
        • 第六步:执行本地windows调试器,生成.dll动态库文件
      • 创建Java程序入口类,加载动态库并运行
        • 第一步:创建Main.java文件,加载动态库,调用方法
        • 第二步:编译Main.java、运行Main
    • Linux系统下编译动态链接库
  • 附录
    • javac参数help
    • 出现的一些问题
      • 关于为什么在`javac`编译的时候要指定`-encoding`选项?
      • 关于为什么要把NaviveDemo.h头文件复制到根目录后加载?
    • 参考链接

背景

        最近学习了Java中调用本地程序(JNI:Java Native Interface)、多种语言混合编程。但是关于Java怎么使用JNI调用本地程序是一点儿都不清楚,网上查阅了很多资料,编写了一个demo做简单调用机制的了解。

        jdk自身在开发中也会调用自己的动态库(windows下的.dll文件),如下图:
1710482988613_B6C76C13-E923-4ee3-8E3F-8B3A78E99127.png

介绍

什么是JNI?

    JNI全称叫Java Navtie Interface,中文翻译本地调用。

C/C++是系统级的编程语言, 可以用来开发任何和系统相关的程序和类库, 但是Java本身编写底层的应用比较难实现, 使用JNI可以调用现有的本地库, 极大地灵活了Java的开发.
C/C++的效率是目前最好的语言, 可以使用C/C++来实现一些实时性非常高的部分. C/C++和Java本身都是非常流行的编程语言, 一些大型软件中经常使用语言之间的混合编程.
以上转载自:https://www.cnblogs.com/jaejaking/p/6840530.html(在Java中调用C/C++本地库)

什么是本地库?

本地库被分为静态库(.a和.lib结尾)动态库(.dll和.so结尾)

  1. 在windows系统下动态库以.dll结尾
  2. 在linux系统下动态库以.so结尾

开发Java使用JNI本地库步骤

  1. 编写Java类,方法要带有native关键字
  2. javac编译Java类,生成class文件
  3. javah生成native对应的头文件(头文件.h)
  4. C/C++实现javah生成的头文件,编译生成.dll动态库
  5. 动态库复制到java类的运行目录下,加载本地库后调用方法、运行

编写Java类实现JNI本地调用

windows系统下编译动态链接库

  • 开发环境:
    1. windows 11系统
    2. jdk8
    3. Visual Studio Code IDE,编写Java代码
    4. Microsoft Visual Studio Community 2022 (64 位),编写C++代码,生成dll动态库
  • 项目结构:

image.png

JNI_TEST
  --java-src   # java源码文件夹 & .dll动态库
  --jni_dll    # c++源码文件夹 & 生成的目标文件(.dll)

创建Java项目(demo)

第一步:编写带有native的Java类
/**
 * Java 本地native方法,具体由C++实现
 */
public class NativeDemo {
    /**
     * 由C++返回一个字符串,通过Java打印出来
     */
    public native String returnString();

}
第二步:javac生成NativeDemo类的字节码文件

打开命令提示符窗口,编译NativeDemo.java文件,生成字节码文件。

image.png

第三步:javah根据字节码文件生成jni头文件(NativeDemo.h)

image.png
        生成的NativeDemo.h,就需要#include 'NativeDemo.h'导入,通过C++去实现了。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class NativeDemo */

#ifndef _Included_NativeDemo
#define _Included_NativeDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     NativeDemo
 * Method:    returnString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_NativeDemo_returnString
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

创建C++动态链接库(DLL)

第一步:打开Microsoft Visual Studio 2022创建项目

搜索dll,创建动态链接库。

image.png

第二步:配置项目并创建

image.png

第三步:加载javah生成的NativeDemo.h头文件

        把javah生成的NativeDemo.h头文件复制到jni_dll文件夹的根目录下。加载生成的头文件。

image.png
image.png

第四步:配置jni.h导入找不到问题

        打开加载的NativeDemo.h头文件后,发现jni.hJNIEXPORTJNICALL加载不到,需要对项目进行配置,导入jdk相关到项目,才能使用jni.h。

image.png
image.png
选择完成,应用后,导入的jni.h头文件不会报错了。

第五步:编辑源码,导入NativeDemo.h头,实现对应方法。

打开pch.cpp源码文件,编辑。

image.png

// pch.cpp: 与预编译标头对应的源文件

#include "NativeDemo.h"
#include "pch.h"
#include <iostream>

// 当使用预编译的头时,需要使用此源文件,编译才能成功。
/*
 * Class:     NativeDemo
 * Method:    returnString
 * Signature: ()Ljava/lang/String;
 * 复制NativeDemo.h头中定义的方法,c++去实现
 */
JNIEXPORT jstring JNICALL Java_NativeDemo_returnString
(JNIEnv* env, jobject jobj) {

	return env -> NewStringUTF("exec dll: this is return from c++");
}

第六步:执行本地windows调试器,生成.dll动态库文件

image.png
        在jni_dll项目的根路径下,x64/Debug/jni_dll.dll就是生成的目标文件,后续被调用的本地动态库也是这个文件。

        到此,创建并生成.dll动态链接库已经完成。

创建Java程序入口类,加载动态库并运行

第一步:创建Main.java文件,加载动态库,调用方法

/**
 * 程序运行入口
 */
public class Main {

    static {
        /**
         * 加载动态库:只需要加载名字就可以,不需要带上.dll后缀,动态库放在和Main运行文件同一个目录下.
         * window上的动态库以.dll结尾,linux动态库以.so结尾
         */
        System.loadLibrary("jni_dll");
    }

    public static void main(String[] args) {
        // 创建Java对象,直接调用方法,具体的实现交给C++底层处理
        NativeDemo demo = new NativeDemo();
        // 调用方法, 由动态库制定并返回
        System.out.println(demo.returnString());

    }
}
第二步:编译Main.java、运行Main

        复制刚生成的jni_dll.dll动态库到可运行文件所在目录,动态库会在此目录下加载。

image.png

Linux系统下编译动态链接库

待补充…

附录

javac参数help

image.png

出现的一些问题

关于为什么在javac编译的时候要指定-encoding选项?

        大多数ide默认的编码环境是utf-8,windows命令提示符窗口,默认是GBK编码。如果使用javac命令直接编译,会出现字符不兼容的错误。所以在javac编译的时候指定使用utf-8的方式进行。

image.png
        可以使用chcp命令查看当前命令提示符窗口的编码方式。

image.png
        修改编码方式后编译同样失败,可能的原因是当前窗口的编码对编译并不生效。
        查阅了相关资料,如果直接对语言和区域的格式进行调整,可能会造成在dos窗口下导致其他字符显示错误。
image.png

关于为什么要把NaviveDemo.h头文件复制到根目录后加载?

        在Microsoft Visual Studio 2022版本编辑器下,加载的头文件不会直接导入项目,在使用#include 'NativeDemo.h'导入头文件的时候,还是会出现找不到头文件的情况。

参考链接

  1. 在Java中调用C/C++本地库
  2. Windows: 转换cmd窗口的默认字符编码 - 夜行过客 - 博客园
  3. windows下vscode+vs2019开发JNI_vscode java jni 的 java.library.path-CSDN博客
  4. VS2019中C++,#include无法打开自己所写的头文件(.h)_vs2019 include报错-CSDN博客
  5. 静态库与动态库的区别与优缺点_静态库和动态库的优缺点-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/481566.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习_微调_7

目标 微调的原理利用微调模型来完成图像的分类任务 微调的原理 微调&#xff08;Fine-tuning&#xff09;是一种在深度学习中广泛应用的技术&#xff0c;特别是在预训练模型&#xff08;Pretrained-Models&#xff09;的基础上进行定制化训练的过程。微调的基本原理和步骤如下…

CRM软件推荐2024:五款顶级产品解析,助您找到最佳选项!

一天之计在于晨&#xff0c;一年之计在于春。 2024年&#xff0c;民营经济发展继续壮大&#xff0c;这对于各行各业而言都是一种机遇挑战。企业想要规范化客户管理&#xff0c;实现销售增长&#xff0c;CRM软件仍然是一个不错的选择。在数字化时代&#xff0c;企业数字化转型已…

预防颈椎病,从职场健康做起

随着现代社会工作方式的转变&#xff0c;职场人士长时间伏案工作&#xff0c;颈椎病的发病率逐渐上升。本文将介绍一些实用的预防颈椎病的方法&#xff0c;帮助职场人士保持健康&#xff0c;提高工作效率。 一、了解颈椎病 颈椎病是指颈椎间盘退行性变及其继发性椎间关节病理性…

基于Python实现高德地图找房系统-爬虫分析

概要 针对大学毕业生对于工作地周边交通出行情况不了解、租房困难等问题,本文主要研究了厦门市的租房信息及地铁公交出行路线,利用Python爬虫爬取58同城上厦门市的租房信息,并进行处理分析,再通过高德地图API将房源信息展示在地图上,实现了基于高德地图API的租房地图。 关键词&…

基于Spring Boot技术的幼儿园管理系统

摘 要 随着信息时代的来临&#xff0c;过去的传统管理方式缺点逐渐暴露&#xff0c;对过去的传统管理方式的缺点进行分析&#xff0c;采取计算机方式构建幼儿园管理系统。本文通过课题背景、课题目的及意义相关技术&#xff0c;提出了一种活动信息、课程信息、菜谱信息、通知公…

Angular入门问题小本本

1、console.log打印object对象显示[object object] 解决方案&#xff1a;使用JSON.stringify console.log(JSON.stringify($rootScope.MaintainDeviceInfo));2、 State ‘goDiskManagement’’ is already defined 解决方案&#xff1a;同一个项目中&#xff0c;不能定义相同…

基于骨骼的动作识别的行动结构图卷积网络

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;基于骨骼的动作识别的行动结构图卷积网络1、研究背景2、方法提出3、关键结构3.1、A-links inference module (AIM)3.2、Structura…

MyBatis3源码深度解析(二十)动态SQL实现原理(一)动态SQL的核心组件

文章目录 前言第八章 动态SQL实现原理8.1 动态SQL的使用8.1.1 \<if>8.1.2 <where|trim>8.1.3 <choose|when|otherwise>8.1.4 \<foreach>8.1.5 \<set> 8.2 SqlSource组件&BoundSql组件8.3 LanguageDriver组件8.3.1 XMLLanguageDriver8.3.2 Ra…

leetcode 20.有效的括号 JAVA

题目 思路 括号的匹配&#xff0c;这是一道经典的栈的应用问题。 给我们一个字符串&#xff0c;当我们遍历到左括号时&#xff0c;让其入栈。当我们遍历到右括号时&#xff0c;让栈顶元素出栈&#xff0c;看看栈顶的元素是否和遍历到的右括号匹配。不匹配的话直接false,匹配的…

vue2 脚手架

安装 文档&#xff1a;https://cli.vuejs.org/zh/ 第一步&#xff1a;全局安装&#xff08;仅第一次执行&#xff09; npm install -g vue/cli 或 yarn global add vue/cli 备注&#xff1a;如果出现下载缓慢&#xff1a;请配置npm 淘宝镜像&#xff1a; npm config set regis…

java算法第32天 | ● 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II

122.买卖股票的最佳时机II 本题中理解利润拆分是关键点&#xff01; 不要整块的去看&#xff0c;而是把整体利润拆为每天的利润。假如第 0 天买入&#xff0c;第 3 天卖出&#xff0c;那么利润为&#xff1a;prices[3] - prices[0]。 相当于(prices[3] - prices[2]) (prices[…

XSS-labs详解

xss-labs下载地址https://github.com/do0dl3/xss-labs 进入靶场点击图片&#xff0c;开始我们的XSS之旅&#xff01; Less-1 查看源码 代码从 URL 的 GET 参数中取得 "name" 的值&#xff0c;然后输出一个居中的标题&#xff0c;内容是 "欢迎用户" 后面…

手撕算法-买卖股票的最佳时机 II(买卖多次)

描述 分析 使用动态规划。dp[i][0] 代表 第i天没有股票的最大利润dp[i][1] 代表 第i天持有股票的最大利润 状态转移方程为&#xff1a;dp[i][0] max(dp[i-1][0], dp[i-1][1] prices[i]); // 前一天没有股票&#xff0c;和前一天有股票今天卖掉的最大值dp[i][1] max(dp[i-1…

智能财务新选择!Zoho Books入选福布斯榜单,助力中小企业!

放眼全球&#xff0c;中小企业始终是经济发展的重要组成部分。然而&#xff0c;由于中小企业的规模、流程规范和资源等方面受限较多&#xff0c;从而导致其在管理及运营上存在着诸多问题。其中包括财务管理不规范、成本控制不到位、运营效率低下等&#xff0c;这些问题则直接影…

如何在CentOS安装SQL Server数据库并实现无公网IP远程连接内网数据库

文章目录 前言1. 安装sql server2. 局域网测试连接3. 安装cpolar内网穿透4. 将sqlserver映射到公网5. 公网远程连接6.固定连接公网地址7.使用固定公网地址连接 前言 简单几步实现在Linux centos环境下安装部署sql server数据库&#xff0c;并结合cpolar内网穿透工具&#xff0…

基于GD32E230C8T6的数字示波器

基于GD32E230C8T6的数字示波器 文章目录 基于GD32E230C8T6的数字示波器基于GD32E230C8T6的数字示波器实物演示电路原理**模拟前端处理电路**image.png**交直流耦合电路****输入信号衰减电路****信号调理电路****虚断:****虚短:****电压跟随器****反相比例放大器****同相比例放…

深度剖析GNSS高精度定位原理

一、背景 目前室外使用最广泛的定位手段是GNSS定位&#xff0c;常规的GNSS定位精度约5、10米左右&#xff0c;无法满足高精度场景的应用&#xff0c;如何提升GNSS定位性能是亟待解决的问题。本文由浅入深剖析GNSS定位原理并介绍如何实现厘米级高度定位。 二、GNSS定位原理 1、…

MySQL下载安装和本地连接

1、下载MySQL 从MySQL官网下载MySQL Community Server版本&#xff1a; 下载地址&#xff1a;MySQL官网 1、进入官网&#xff0c;点击DOWNLOADS 2、点击MySQL Community(GPL)Downloads 3、点击MySQL Installer for Windows 4、这个会直接跳转到最新的版本 如果想下载以往的…

面试算法-83-不同路径 II

题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么从左上角到…

【进程概念】启动进程 | 查看进程 | 创建进程

目录 启动进程 查看进程 方法1&#xff1a;/proc 方法2&#xff1a;查看脚本 ​方法3&#xff1a;系统调用获取进程标示符❗❗ 终止进程 创建进程&#xff08;主fork) &#x1f642;查看父子进程的pid &#x1f642;进程创建/执行/终止 &#x1f642;多次重新启动进…