1. Java调用本地代码常见的两种方案

  • JNI

JNI(Java Native Interface),有过不同语言间通信开发经历的一般都知道,它允许java和其他语言代码(尤其是C/C++)进行交互,只要遵守约定即可。首先看下JNI调用C/C++过程,注意写程序时自下而上,调用时自上而下:

可见步骤之多,调用.dll/.so共享库之痛苦的过程。

若已有编译好的.dll/.so文件 —> 需先用是C语言另外写一个.dll/.so共享库,使用SUN规定的数据结构代替C语言的数据结构,调用已有的dll/so中公布的函数 —> java中载入这个库 —> java编写Native函数作为链接库中函数的代理

问题是很少有java程序员愿意编写调用.dll/.so库中原生函数的java程序,这也使java在客户端上乏善可言,是JNI的一大弱点!

  • JNA

JNA提供一组Java工具类用于在运行期间动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射。

简而言之,就是jna基于jni的方式封装了很多api,在使用上面相对于jni来说简化了很多。

但是JNA不能完全替代JNI,JNI不仅可以实现java访问C,也可实现C调用java。

而JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,有些情况还是需要使用JNI技术。

2. 安装VS2022

  • 下载 VS2022

下载 VS2022 时,现在社区版即可。

https://visualstudio.microsoft.com/zh-hans/vs/

下载下来是一个在线安装的安装器VisualStudioSetup.exe,双击运行即可。安装选择 使用C++的桌面开发 即可:

3. 创建java项目

编写本地方法

public class JniDemo {// 声明本地方法public native int add(int a, int b);public native int sub(int a, int b);}

使用javah生成c/c++头文件

javah com.jnidemo.JniDemo

生成的头文件com_jnidemo_JniDemo.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jnidemo_JniDemo */#ifndef _Included_com_jnidemo_JniDemo
#define _Included_com_jnidemo_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_jnidemo_JniDemo* Method:    add* Signature: (II)I*/
JNIEXPORT jint JNICALL Java_com_jnidemo_JniDemo_add(JNIEnv *, jobject, jint, jint);/** Class:     com_jnidemo_JniDemo* Method:    sub* Signature: (II)I*/
JNIEXPORT jint JNICALL Java_com_jnidemo_JniDemo_sub(JNIEnv *, jobject, jint, jint);/** Class:     com_jnidemo_JniDemo* Method:    acl* Signature: ()D*/
JNIEXPORT jdouble JNICALL Java_com_jnidemo_JniDemo_acl(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif

4. 创建c/c++项目

打开VS2022,创建动态链接库dll项目

输入项目名和存储的目录,点击创建即可

把头文件com_jnidemo_JniDemo.h拷贝到JniTestDemo项目中,并附加到项目里

创建com_jnidemo_JniDemo.cpp源文件,并实现头文件的两个定义的方法

#include "pch.h"
#include <jni.h>
#include "com_jnidemo_JniDemo.h"/*
* Class:     com_jnidemo_JniDemo
* Method : add
* Signature : (II)I
*/
JNIEXPORT jint JNICALL Java_com_jnidemo_JniDemo_add(JNIEnv * env, jobject jobj, jint a, jint b){return a + b;
}/** Class:     com_jnidemo_JniDemo* Method:    sub* Signature: (II)I*/
JNIEXPORT jint JNICALL Java_com_jnidemo_JniDemo_sub(JNIEnv* env, jobject jobj, jint a, jint b){return a - b;
}

添加jdk的jni.h文件到项目中,进行依赖构建

右击项目,现在属性

选择图中这两个目录,做为构建依赖目录;这两个目录分别存在jni.hjni_md.h两个头文件

构建c/c++项目

另外要特别注意编译的dll的x86与x64一定要与JDK的版本对应,否则在java调用dll时会出现以下错误:

Can't load IA 32-bit .dll on a AMD 64-bit platform

5.编写java代码调用dll

package com.jnidemo;public class JniDemo {// 声明本地方法public native int add(int a, int b);public native int sub(int a, int b);static {System.out.println(System.getProperty("java.library.path"));// x64System.load("E:\\dllws\\JniTestDemo\\x64\\Debug\\JniTestDemo.dll");}public static void main(String[] args) {JniDemo ob = new JniDemo();System.out.println(ob.add(1, 2));System.out.println(ob.sub(2, 3));}}

6. 加载dll&so库文件的路径java.library.path说明

  • Java的System.loadSystem.loadLibrary都可以用来加载库文件。例如可以这样载入一个windows平台下JNI库文件:

System.load("D://dll//TestJNI.dll"); //绝对路径
  • System.loadLibrary参数为库文件名

例如可以这样载入一个windows平台下JNI库文件

System.loadLibrary ("TestJNI");

这里TestJNI必须在java.library.path这一jvm变量所指向的路径中,可以通过如下方法获得该变量的值:

System.getProperty("java.library.path");

默认情况下,Windows平台下包含下面的路径:

1)和jre相关的目录

2)程序当前目录

3)Windows目录

4)系统目录(system32)

5)系统环境变量path指定的目录

  • 在linux下添加一个java.library.path的方法如下: 在/etc/profile后面加上一行

export LB_LIBRARY_PATH=路径
  • 在执行程序的时候可以显示指定,-Djava.library.path=路径,这种会清除掉预设置的java.library.path的值。

java -jar -Djava.library.path=/usr/lib TestJni.jar

Windows 下 JNI 调用动态链接库 dll相关推荐

  1. Unity调用动态链接库dll和so

    [001]Unity调用动态链接库dll和so  ApolloAR https://www.jianshu.com/p/f37bb72979a1 一.PC平台 (注:环境 VS2017+Unity20 ...

  2. Windows 下的 7 种 DLL 劫持技术

    本文讲的是Windows 下的 7 种 DLL 劫持技术,在本文中,我将列出半打可以在Windows运行用户模式的进程中使用DLL注入技术.也许可能会有更多类似的技术,但我正在和你分享的是我所拥有的第 ...

  3. Windows下Java调用BAT批处理不弹出cmd窗口

    常规Windows下Java调用BAT方式肯定会弹出cmd窗口 Runtime.getRuntime().exec("cmd.exe /C start D:\\test.bat") ...

  4. windows 下java调用winrar压缩文件为rar 格式

    windows  下java调用winrar压缩文件为rar 格式 import java.io.BufferedReader; import java.io.IOException; import ...

  5. VC++6.0如何创建与调用动态链接库(dll)

    VC++支持的DLL: DLL的编制与具体的编程语言及编译器无关,动态链接库随处可见,VC++支持三种DLL:非MFC动态库.MFC规则DLL和MFC扩展DLL.DLL导出函数(或变量.类)可供应用程 ...

  6. Qt生成调用动态链接库dll

    把编译好的包含函数和变量的目标代码存储到文件中,在链接的时候让链接程序自动从文件中查找需要的代码.这个文件就是链接库,又可以分为静态链接库和动态链接库. 1. 静态链接库 链接程序从库中寻找需要的符号 ...

  7. windows下gethostbyname 调用失败

    gethostbyname()函数属于WinSock API库,而在使用WinSock API之前,必须调用WSAStartup函数,只有该函数成功返回(表示应用程序与WinSock库成功地建立起连接 ...

  8. Python调用动态链接库DLL文件

    目录 方法一.ctypes库方式 方法二.shell方式 方法一.ctypes库方式 使用ctypes库调用.这个方法网上一搜都是. import ctypes obj = ctypes.WinDLL ...

  9. Matlab调用动态链接库DLL文件

    环境:vs2015.Matlab2020 VS2015中建立工程, 建立工程如下两图所示 在头文件和源文件中分别添加头文件和源文件(代码如下所示) 头文件matdll.h文件 #pragma once ...

最新文章

  1. OpenCV中泛洪填充算法解析与应用
  2. ubuntu android2.3 emulator,Android Studio 2.3 Ubuntu 16.10 emulator do not start
  3. Gradle 设置 本地maven仓库及发布mavenLocal()路径的方法
  4. 电影点评系统论文java_毕业设计(论文)-基于web的电影点评系统分析与设计.docx...
  5. StringBoot设置了拦截器没有产生作用,页面没有拦截
  6. php redis命令大全,redis中key相关命令详解
  7. android集成测试工具,android – 集成测试和Cucumber测试
  8. Np计算机领域,我国数学家证明NP=P
  9. 再谈SQL Server中日志的的作用
  10. C++ 对象关系映射(ORM)介绍
  11. I.MX6 mfgtool2-android-mx6q-sabresd-emmc.vbs hacking
  12. Windows下python的配置
  13. esxi 环境 西数硬盘测试软件,总算基本完美的折腾好ESXI+群晖+NVME
  14. xshell文件传输乱码_xshell5 显示中文乱码解决方法,远程连接Linux CentOS
  15. 转速恒压频比交流变频调速系统Simulink仿真,可观察到电压频率的变比情况以及电动机的转速波形。
  16. 汽车CAN诊断——报文数据篇
  17. 学会这5种排版方式,设计能力分分钟就能提高
  18. 小学计算机课程听课记录,小学信息技术听课记录
  19. 作业中关于H5中动画的实现——animation
  20. Excel表格如何设置成不可编辑的模式?

热门文章

  1. 如何制作新毛桃装机u盘
  2. linux usb ehci controller driver
  3. 已经三十多岁了还是一事无成,还能靠做自媒体翻身吗?
  4. 施金源:6.19下周黄金价格走势预测?及下周黄金操作建议
  5. H5移动端剪切上传头像
  6. 【linux性能优化】CPU上下文切换
  7. VR全景助力健身房品牌升级,大幅度提升用户到店率
  8. ansible file 模块
  9. HTTP错误 403.14 - Forbidden 错误的解决方法
  10. 什么是事务,事务的用途,分布式事务