公司的硬件让我帮忙调用一个so文件,想着一直都没机会自己写一个jni,于是就答应了,在调用的过程中还踩了不少坑,特地写一篇博客记录一下。


一、使用技术

原本是想直接用java自带的jni,但是我们硬件只给了一个so文件,而且里面的函数命名等规则不符合java的jni调用标准,于是就打算使用框架jna来调用。

JNA就是建立在JNI之上,它简化了Java调用原生函数的过程。JNA提供了一个动态的C语言编写的转发器(实际上也是一个动态链接库)可以自动实现Java与C之间的数据类型映射。从性能上会比JNI技术调用动态链接库要低,但开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射,大大降低了Java调用本体共享库的开发难度。

二、编码前准备

2.1 首先将so文件放在项目resource文件夹下:

之所以放在该目录下,是为了方便编码过程中能动态获得该文件的路径,其实so文件可以放在任意路径下,只需在加载该so文件的时候,传入的文件的路径给加载器即可。

2.2 引入jna的jar包

有两种引入方式:

一、直接在网上下载jna-3.0.9.jar,然后手动引入jar包

二、在pom.xml中引入[仅限maven项目]

    <dependency><groupId>com.sun.jna</groupId><artifactId>jna</artifactId><version>3.0.9</version></dependency>

ps: 有一个地方需要注意一下,如果你用的是idea,在jar包引入后可能还是会出现ClassNotFoundException,这个时候可以参考以下步骤:

完成上述步骤即可解决该异常


三、开始编码

3.1准备一个类,用于解析so文件

package com.appcups.energy.chargingstation.server.chargingstationsysapi.jna;import com.sun.jna.Library;
import com.sun.jna.Native;//继承Library,用于加载库文件
public interface Clibrary extends Library {// [Native.synchronizedLibrary] 阻止多线程同时访问本地代码Clibrary INSTANTCE = (Clibrary) Native.synchronizedLibrary((Clibrary) Native.loadLibrary(Clibrary.class.getResource("/secret_udp.so").getPath().substring(1)// substring(1)的原因是在Windows下获取到的路径前面会多一个斜杠,但在Linux下不会, Clibrary.class));// 此方法为so文件中的c语言函数1 -> int test_return_C(void);//  ##备注: 这里的void代表无参int test_return_C();// 此方法为so库中的c语言函数2 -> char* Decrpyt( char * input);// ## 备注: 这里的char* 是c语言中的指针,与java中的String相对应String Decrpyt(String input);}

注: 对于so文件中c类型与java类型的映射关系,可以参考下图:


3.2 编写测试类

public class Demo {public static void main(String[] args) {Clibrary instance = Clibrary.INSTANTCE;// 方法一int result = instance.test_return_C();// 方法二String arr = instance.Decrpyt("方法二参数");}}

测试完毕,可以将函数调用返回值打印到控制台,查看调用结果

四、将项目部署到Linux

我将项目直接部署到Linux是无法正常运行的,需要修改 Clibrary.java 类,因为Linux下使用getResource()方法获取到的路径是正确的,只有在Windows上调用getResource()方法才会多出一条斜杠,所以在Linux下需要将类中的.subString(1)方法的调用删掉,为了让代码兼容Windows和Linux操作系统,我将Clibrary.java 类修改为以下代码:

import com.sun.jna.Library;
import com.sun.jna.Native;//继承Library,用于加载库文件
public interface Clibrary extends Library {String os = System.getProperty("os.name");  // 获取当前操作系统的类型int beginIndex = os != null && os.startsWith("Windows") ? 1 : 0;// windows操作系统为1 否则为0Clibrary INSTANTCE = (Clibrary) Native.synchronizedLibrary((Clibrary) Native.loadLibrary(Clibrary.class.getResource("/secret_udp.so").getPath().substring(beginIndex), Clibrary.class));// 此方法为so文件中的c语言函数1 -> int test_return_C(void);//  ##备注: 这里的void代表无参int test_return_C();// 此方法为so库中的c语言函数2 -> char* Decrpyt( char * input);// ## 备注: 这里的char* 是c语言中的指针,与java中的String相对应String Decrpyt(String input);}

代码通过获取当前系统的操作类型来改变调用substring的作用域,实现了兼容性。

但在代码运行时,还是报错了:

参考王小草的博客,发现在Windows下生成的so文件是无法在Linux上运行的,因为不同系统生成的文件的ELF header可能是不一样的,所以让硬件工程师在Linux下重新生成了一个so文件,发现竟然真的没有报错了

写在最后: 如需转载,请注明出处,如有问题,欢迎在评论区留言.

====== 2020-06-19 ======

网上有人遇到这样的报错:java.lang.UnsatisfiedLinkError: Unable to load library 'lib/HCNetSDK': ÕҲ»µ½ָ¶;我无法复现。。能不能有人分享个so文件给我,我调试一下,给百度云链接或者csdn下载链接都行

这个问题博主解决不了 大家可以参考:https://www.cnblogs.com/xdk1002/p/13218980.html

Java调用so文件相关推荐

  1. 关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序。

    关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. 参考文章: (1)关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. (2)https://www. ...

  2. 关于java调用Dll文件的异常 Native library (win32-x86-64/CtrlNPCDLL.dll) not found in resource pat

    关于java调用Dll文件的异常 Native library (win32-x86-64/CtrlNPCDLL.dll) not found in resource pat 参考文章: (1)关于j ...

  3. java调用python文件的几种方式【超细讲解!】

    java调用python的契机来自于一个项目需要用到算法,但是算法工程师们写的python,于是就有了java后端调用python脚本的需求,中间遇到了许多问题,特此记录整理了一次. 1.java调用 ...

  4. Java调用kjb文件

    目录 一.kjb和ktr文件创建 kjb文件 ktr文件 关联kjb和ktr 变量信息 二. Java代码调用kjb 引包 放入kjb和ktr文件 三.代码调用 定时任务 一.kjb和ktr文件创建 ...

  5. JAVA 调用 DLL 文件 TSCLIB.DLL TSC打印机

    这是一段JAVA调用TSC条码打印机的代码:有详细的注释! 1,需要把dll文件拷贝到c:\windows\system32目录下 2,工程里面需要加载JNative.jar包(网上很多下载的) /* ...

  6. java 调用 swf 文件上传_java SpringMvc 实现文件在线预览(openoffice+swftools+flexpaper)

    项目需求:服务器接受的文件当下只能下载之后才能浏览内容,现需要后台能在线浏览到文件内容,避免繁琐无用文件下载操作. 通过几天网上资料搜索,目前免费的在线预览开发技术使用最多还是(openoffice+ ...

  7. Java调用库文件(JNI)(android对此有所改变)

    1.准备java 程序 testdll.java,内容为: public class testdll {  static {  System.loadLibrary("goodluck&qu ...

  8. java 调用 swf 文件上传_java文件上传方法

    文件上传方法(一次上传一个文件,多个文件的话,请写循环调用) Upload.uploadFile(theFile, filePath) 说明: theFile:类型是FormFile filePath ...

  9. 关于Java调用dll文件的一系列问题(持续更新)

    最近做项目,需要调用dll库,出现了一些问题,此处记录下,以免再踩坑. 报Unable to load library 'xxx.dll', 等错误 1.将你要用到的dll库放到 "C:\W ...

  10. java调用.sh文件_java 调用cmd/sh文件

    最近在做产品遇到java在windows下面调用bat脚本和在linux下调用shell脚本,现在记录一下以便以后查阅. 首先贴出RuntimeUtils工具类,此类简化了 Runtime中exec的 ...

最新文章

  1. 高清视频实时对讲SDK源码
  2. java 18 -4 LinkedHashMap集合
  3. 调试U-Boot笔记(三)
  4. 35. 脱壳篇-UPX和WinUpack压缩壳的使用和脱法
  5. android 远程桌面 windows7,WIN7实现多用户远程桌面
  6. android没有界面app,Android离线打包 app处于原生界面 切换到桌面再点击app 原生界面被关闭...
  7. 数据库-Linux系统下的命令
  8. 双螺杆制冷压缩机行业调研报告 - 市场现状分析与发展前景预测
  9. Java 8 八年不倒、IntelliJ IDEA 力压 Eclipse,2022 年 Java 开发者都在用什么?
  10. 学会了C语言你可以独立开发这些项目。。。。
  11. web文件上传(三)--webapi后台接收参数和文件
  12. intellji External Libraries下依赖包找不到解决方法
  13. Atitit spring原理 反射 ioc 与注解api 目录 1. 反射的使用 1 1.1. 使用jdk原生反射api 1 1.2. 使用apache 工具包 commons-beanutil
  14. html5 查询展示页面,基于Html5的可视化展示页面自动发布方法及系统与流程
  15. CAD如何一键解决批量打印
  16. 数据分析项目分析之风控建模!!
  17. tplink连接服务器失败_tplink路由器网络已连接但是上不了网怎么办?
  18. 京都计算机学院放假时间表,2018年官方放假安排时间一览表
  19. oracle测试实用SQL语句
  20. CISSP第6/8知识点错题集

热门文章

  1. 2021年4月自考04741计算机网络原理试卷
  2. 计算机毕业设计安卓旅游APP源码
  3. 春节没事,看几部黑客电影吧!
  4. NAT端口映射到物理机
  5. 中原证券同花顺个股期权全真模拟交易客户端
  6. 猎豹网校 ASP.NET全套教程
  7. java jboss_jboss配置方法简明教程
  8. rapidxml 给节点赋值时出现乱码问题
  9. Mac配置OpenGL环境
  10. QQ空间的汉字转拼音代码