Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 768|回复: 0

Java导出成可运行Jar包 dll或者so加载失败的解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-9-1 15:24:26 | 显示全部楼层 |阅读模式

    正常情况下, xxx.class.getResourceAsStream(lib) 这样就可以获取到了。但是我的是在JFrame的初始化中的, 所以需要Thread.currentThread().getContextClassLoader().getResourceAsStream(lib); 这样来获取。   这个坑  找了蛮久才找到解决方案记录下。

    嗯   看了一些解决方案,1、把库跟jar包一起拷贝打包 2、放入指定路径 添加环境变量 通过环境变量来获取库路径等等 终究还是比较麻烦的。  

    经过测试发现  本文的方案 还是没有最终解决这个问题   手里还有别的事  先放下了后面再研究

    private synchronized static void copyLib(String libFullName, String arch_libfile_suffix) throws IOException {
        InputStream in = null;   
        BufferedInputStream reader = null;   
        FileOutputStream writer = null;   
        File f = new File(".");
        
        String libs[] = { libFullName, libFullName.replace(arch_libfile_suffix, ".c"), libFullName.replace(arch_libfile_suffix, ".h") }; 
        for(int i = 0;i<libs.length;++i){
            File extractedLibFile = new File(f + File.separator + libs);   
            if(!extractedLibFile.exists()){   
                //打包进jar中后, 可以用zip软件打开jar文件 看看你需要调用的dll或者so 在jar中的路径就是这个lib的值       
                String lib = libs.replace("lib" + File.separatorChar, "");
    //          String lib = libs;
                System.out.println("lib = " + lib);
                try {
                    // “/”代表Jar包的根目录
                    in = Thread.currentThread().getContextClassLoader().getResourceAsStream(lib);
                    //   踩过的坑  这些方式都没能够成功获取到。   这是因为我的获取是在UI线程中的。
                    //   MD5.class.getResourceAsStream("/" + libs);
                    //   MD5.class.getClassLoader().getResourceAsStream("/" + libs);
                    //   MD5.class.getResource(libFullName);
                    System.out.println(" getResourceAsStream == " +  lib);
                   
                    reader = new BufferedInputStream(in);
                    writer = new FileOutputStream(extractedLibFile);
     
                    byte[] buffer = new byte[1024];         
                    while (reader.read(buffer) > 0){
                        writer.write(buffer);
                        buffer = new byte[1024];
                    }
                } catch (IOException e){
                    e.printStackTrace();
                } finally {
                    if(in!=null)
                        in.close();
                    if(writer!=null)
                        writer.close();
                }
            }   
        }   
    }

    这种方案  经过测试在mac上面是可行的   但是在windows上面 总是拷贝lib失败  报 IOException 异常. 先记录 后面再解决

     

     

     还有下面这种解决方案,来自https://www.cnblogs.com/FlyingPuPu/p/7598098.html

     就是把Jar 当作zip文件遍历,找出需要加载的lib 然后拷贝到指定路径再进行加载

    /**
     * 加载项目下的native文件,DLL或SO
     *
     * @param dirPath 需要扫描的文件路径,项目下的相对路径
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException {
        Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath);
        // 获取操作系统类型
        String systemType = System.getProperty("os.name");
        String systemArch = System.getProperty("os.arch");
        // 获取动态链接库后缀名
        String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
        while (dir.hasMoreElements()) {
            URL url = dir.nextElement();
            String protocol = url.getProtocol();
            if ("jar".equals(protocol)) {
                JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                JarFile jarFile = jarURLConnection.getJarFile();
                // 遍历Jar包
                Enumeration<JarEntry> entries = jarFile.entries();
                while (entries.hasMoreElements()) {
                    JarEntry jarEntry = entries.nextElement();
                    String entityName = jarEntry.getName();
                    if (jarEntry.isDirectory() || !entityName.startsWith(dirPath)) {
                        continue;
                    }
                    if (entityName.endsWith(ext)) {
                        loadJarNative(jarEntry);
                    }
                }
            } else if ("file".equals(protocol)) {
                File file = new File(url.getPath());
                loadFileNative(file, ext);
            }
        }
    }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-22 18:55 , Processed in 0.056253 second(s), 28 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表