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

查看:178
本文介绍了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:


线程mainjava中的异常.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:\Users\Supertreta\Desktop\nm files\temp\jniBin.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。您必须采取中间步骤将DLL复制出JAR。下面的代码应该这样做:

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天全站免登陆