Java - 通过相对路径加载 dll 并将它们隐藏在 jar 中 [英] Java - Loading dlls by a relative path and hide them inside a jar

查看:31
本文介绍了Java - 通过相对路径加载 dll 并将它们隐藏在 jar 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应该作为 jar 发布的 Java 应用程序.该程序依赖于 JNI 调用的 C++ 外部库.为了加载它们,我使用带有绝对路径的 System.load 方法,这很好用.

I am developing a Java application that should be release as a jar. This program depends on C++ external libraries called by JNI. To load them, I use the method System.load with an absolute path and this works fine.

但是,我真的很想将它们隐藏"在 JAR 中,因此我创建了一个包来收集它们.这迫使我加载一个相对路径 - 包路径.通过这种方法,我让用户可以在任何目录中运行 JAR,而不必担心链接 DLL 或对之前的安装过程感到厌烦.

However, I really want to "hide" them inside the JAR, so I have created a package to collect them. This forces me to load an relative path - the package path. By this approach, I let the user run the JAR in any directory, without being worried about linking the DLLs or bored with a previous installation process.

这会引发预期的异常:

线程main"中的异常java.lang.UnsatisfiedLinkError:需要库的绝对路径

Exception in thread "main" java.lang.UnsatisfiedLinkError: Expecting an absolute path of the library

我怎样才能让它工作?

将 DLL 复制到文件夹(如下所述)的方法仅在我在 eclipse 环境下运行时才有效.运行导出的 JAR,DLL 二进制文件创建良好,但加载 JNI 会引发下一个异常:

The approach of copying the DLLs to a folder (explained below) only works when I run it under the eclipse environment. Running an exported JAR, the DLL binaries are well created but loading the JNI one throws the next exception:

线程main"中的异常java.lang.reflect.InvocationTargetException

Exception in thread "main" java.lang.reflect.InvocationTargetException

 at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)
 Caused by: java.lang.UnsatisfiedLinkError: C:UsersSupertretaDesktop
m files	empjniBin.dll: Can't find dependent libraries at java.lang.ClassLoader$NativeLibrary.load(Native Method)

我运行这个加载方法:

public static void loadBinaries(){
        String os = System.getProperty("os.name").toLowerCase();

        if(os.indexOf("win") >= 0){
            ArrayList<String> bins = new ArrayList<String>(){{
                add("/nm/metadata/bin/dependence1.dll");
                add("/nm/metadata/bin/dependence2.dll");
                add("/nm/metadata/bin/dependence3.dll");
                add("/nm/metadata/bin/dependence4.dll");
                add("/nm/metadata/bin/jniBin.dll");
            }};

            File f = null;
            for(String bin : bins){
                InputStream in = FileManager.class.getResourceAsStream(bin);
                byte[] buffer = new byte[1024];
                int read = -1;
                try {
                    String[] temp = bin.split("/");
                    f = new File(TEMP_FOLDER, temp[temp.length-1]);     
                    FileOutputStream fos = new FileOutputStream(f);

                    while((read = in.read(buffer)) != -1) {
                        fos.write(buffer, 0, read);
                    }
                    fos.close();
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            System.load(f.getAbsolutePath());
        }
    }

我认为这可能是访问权限问题,但不知道如何解决.你怎么看?

I think this could be an access privileges issue, but don't know how to solve it. What do you think?

推荐答案

我不相信您可以直接从 JAR 加载 DLL.您必须采取从 JAR 中复制 DLL 的中间步骤.下面的代码应该这样做:

I don't believe you can load the DLL directly from the JAR. You have to take the intermediary step of copying the DLL out of the JAR. The following code should do it:

public static void loadJarDll(String name) throws IOException {
    InputStream in = MyClass.class.getResourceAsStream(name);
    byte[] buffer = new byte[1024];
    int read = -1;
    File temp = File.createTempFile(name, "");
    FileOutputStream fos = new FileOutputStream(temp);

    while((read = in.read(buffer)) != -1) {
        fos.write(buffer, 0, read);
    }
    fos.close();
    in.close();

    System.load(temp.getAbsolutePath());
}

这篇关于Java - 通过相对路径加载 dll 并将它们隐藏在 jar 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆