首页 > 其他分享 >JNA加载存在多个依赖的so动态库

JNA加载存在多个依赖的so动态库

时间:2023-12-06 10:46:01浏览次数:24  
标签:LD jna JNA so 分片 PATH 动态 com 加载

之前记录过在windows上加载单个ddl动态库(JNA简单使用(一)(java和c++互操作) - 浪迹天涯的派大星 - 博客园 (cnblogs.com)),这次记录一下在linux上调用存在多个依赖的so动态库。

1、背景

需要c++分片处理一种特殊格式的文件,Java接受分片数据后保存,采用JNA的方式调用c++动态库的方式实现。

2、Java代码

注:此处Java精简了逻辑,只为简单体现JNA调用c++的方式

2.1、Library接口代码

区别之一:load动态库时,windows上ddl不用写后缀,linux上so需要写后缀

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;

public interface SlicerLibrary extends Library {


    SlicerLibrary LIBRARY = Native.load("libEnv.so", SlicerLibrary.class);

    /**
     * 初始化环境
     *
     * @return 是否成功
     */
    boolean initSlice();

    /**
     * 通知c++清除缓存
     */
    void freeSliceCache();

    /**
     * 文件分片完成,释放资源
     */
    void unInitSlice();

    /**
     * 获取分片数据
     *
     * @param filePath  完整文件路径
     * @param objCounts 每个分片文件包含的实体数量
     * @return 总的分片个数
     */
    Integer fileSlice(WString filePath, int objCounts);

    /**
     * 获取序列号index的分片大小
     *
     * @param index
     * @return 分片大小(单位byte)
     */
    int getSliceBufferLength(int index);


    /**
     * 获取分片数据的字节数组
     *
     * @param index        分片序号
     * @param pSliceBuffer 分片数据
     * @return 是否成功
     */
    boolean getSliceBuffer(int index, Pointer pSliceBuffer);
}

2.2、调用动态库的Java代码

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;

public class SlicerService {

    /**
     * 每个分片中包含的实体数量
     */
    private static final int objCountsPerPackage = 100;

    /**
     * 静态变量,确保不会被JVM垃圾回收
     */
    private static SlicerLibrary library = null;

    /**
     * 初始化动态库标志位
     */
    private static boolean initFlag = false;

    public void saveSliceFile(String filePath) {
        //初始化动态库
        initSliceLibrary();
        //c++对应的数据类型是w_chat
        WString path = new WString(filePath);
        //获取分片数量
        Integer count = library.fileSlice(path, objCountsPerPackage);
        //循环处理所有的分片
        if (count != null && count > 0) {
            for (int i = 0; i < count; i++) {
                //获取每个分片文件的数据长度
                int size = library.getSliceBufferLength(i);
                //分配内存大小
                Pointer buffer = new Memory(size);
                try {
                    if (library.getSliceBuffer(i, buffer)) {
                        //获取数据
                        byte[] data = buffer.getByteArray(0, size);
                        //保存数据
                        saveData(data);
                    }
                } finally {
                    //清除分配的内存
                    Native.free(Pointer.nativeValue(buffer));
                    //避免GC时,重复调用Native.free().而导致程序异常退出
                    Pointer.nativeValue(buffer, 0L);
                    //引用置空,便于垃圾回收
                    buffer = null;
                }
            }
        }
    }

    /**
     * 初始化动态库
     */
    private void initSliceLibrary() {
        if (!initFlag) {
            library = SlicerLibrary.LIBRARY;
            synchronized (this) {
                if (!initFlag) {
                    initFlag = library.initSlice();
                }
            }
        }
    }

    /**
     * 保存实际数据
     *
     * @param data
     */
    private void saveData(byte[] data) {
        //省略保存逻辑
    }
}

3、需要依赖的其他动态库的存放位置

将依赖的动态库,存放在linux服务器的任意文件夹下,然后将文件夹路径,配置进LD_LABRARY_PATH。

例如:/home/test,假设Java需要加载的入口so动态库是test1.so,c++文件工程结构如下:

则应该执行:

export LD_LABRARY_PATH=$LD_LABRARY_PATH:/home/test:/home/test/folder1:/home/test/folder2

注:$LD_LABRARY_PATH的作用是防止之前已经配置的路径被覆盖,在后面增加新的路径即可,多个文件夹路径通过冒号(:)分割。

3、export和LD_LABRARY_PATH说明

3.1、LD_LABRARY_PATH

LD_LABRARY_PATH是用于指定动态链接器(ld)查找ELF可执行文件运行时所依赖的动态库(so)的路径。即用于在程序运行期间查找动态链接库时,指定除了系统默认路径(/usr/lib)之外的路径。

LD_LABRARY_PATH,无法识别文件夹里面的子文件夹,子文件夹需要单独配置

3.2、export

Linux中,export命令用于新增、修改和删除Linux上的环境变量(对PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH),只针对当前用户当前窗口登录有效,新开窗口需要重新执行;

如果要使其永久生效,则需要在linux环境变量中配置,编辑vim ~/.bashrc ,增加export语句,然后source ~/.bashrc,使其立即生效。

参考:1、Linux中修改环境变量及生效方法(永久、临时)环境变量查看_linux 激活环境变量

2、Linux中PATH、 LIBRARY_PATH、 LD_LIBRARY_PATH的区别_ld_library_path library_path 区别

标签:LD,jna,JNA,so,分片,PATH,动态,com,加载
From: https://www.cnblogs.com/zhaodalei/p/17866650.html

相关文章

  • SoundBar_DI
    SoundBar   DTS:X      技术是开放式的新一代的编解码标准,同时也是基于对象的多维空间音频技术(以下简称MDA)。不论是在电影院或家庭环境,DTS:X都能呈现栩栩如生、振人心魄的娱乐体验。观众将获得前所未有维度的沉浸式包围体验。电影院或是家庭影院的用户也可以通过多种......
  • 将json数据导入到ES集群——解决方案对比&填坑日记
    需求将写好的json数据。导入到es集群数据说明文件JSON数据,一行一个JSON。{"id":"d2716ae8fba4e026c4bd9445c3f49e2c","lang":"zh","title":"吉美旅馆","content":"吉美..."}{"id":"d2716ae8fba4e026c4bd9445......
  • 【scikit-learn基础】--『数据加载』之真实数据集
    上一篇介绍了scikit-learn中的几个玩具数据集,本篇介绍scikit-learn提供的一些真实的数据集。玩具数据集:scikit-learn基础(01)--『数据加载』之玩具数据集1.获取数据集与玩具数据集不同,真实的数据集的数据不仅数据特征多,而且数据量也比较大,所以没有直接包含在scikit-learn库中......
  • soildworks——草图基准面遗失
    点击编辑草图基准面 重新选定新基准面   ......
  • Http 获取JSON
    packagecom.ls.utils;importjakarta.servlet.http.HttpServletRequest;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.nio.charset.StandardCharsets;/***@authorLartimes*@version1.0*@des......
  • 5.Websocket实现消息推送
    项目需要一个在线协同办公功能来进行消息实时推送,我采用SpringBoot结合Websocket来实现该功能。Websocket采用全双工通信方式,可以在客户端和服务端之间建立持久的连接,实现实时的双向通信。相对于传统的HTTP请求,WebSocket具有以下优势:实时性:Websocket提供实时的双向通信能力......
  • 每天5分钟复习OpenStack(十二)Ceph FileStore 和 BlueSotre
    一个最小化的Ceph集群需要三个组件MONMGROSD.上一章我们部署了MON,本章节我们完成剩下MGR和OSD的部署。在文末我们将重点介绍下什么是FileStore和BlueStore,并详细分析其特点,来说明为什么Ceph社区放弃了FileStore,直接采用了BlueStore.1、MGR部署创建mgr工作目录sudo-u......
  • [GraphicBufferSource](id:5cd400000003,api:1,p:1674,c:23764) cancelBuffer: Buffer
    开发中遇到的问题,这个问题吧属于我们公司开发使用的RSR然后我们做好的app就是一个录屏软件将视频推到RSR当中去,可是推送的同时只会在RSR中出现一下我查看日志文件输出的信息唯一出现爆红的地方就是GraphicBufferSourcecancelBuffer:BufferQueuehasbeenabandoned这个,有没有经......
  • JSON utils 工具类核心方法parseObject , toString实现
    1packagecom.ls.utils;23importjava.lang.reflect.Array;4importjava.lang.reflect.Field;5importjava.util.Arrays;67/**8*@authorLartimes9*@version1.010*@description:JSON工具类11*toJSONString12*parseObject13......
  • Solidity初学
    https://www.youtube.com/watch?v=xv9OmztShIw&list=PLO5VPQH6OWdVQwpQfw9rZ67O6Pjfo6q-phelloworld//SPDX-License-Identifier:MIT//如果没有上面的license就会出现黄色warning,挺难看的..pragmasolidity^0.8;//指定solidity编译版本,带了^号说明要在该版本(0.8)......