专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
郭霖  ·  从源码到定制:全面解析 Android ... ·  3 天前  
郭霖  ·  HarmonyOS ... ·  6 天前  
郭霖  ·  HarmonyOS ... ·  5 天前  
鸿洋  ·  大图检测插件的落地 ·  4 天前  
鸿洋  ·  Android AppOpsService是什么? ·  6 天前  
51好读  ›  专栏  ›  安卓开发精选

从源码看DL4J中Native BLAS的加载,以及配置(下)

安卓开发精选  · 公众号  · android  · 2016-11-24 23:37

正文

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - 望天

链接:http://android.jobbole.com/85213/

点击 → 了解如何加入专栏作者


接上文


public static synchronized void load(String... paths) {  

    if(paths != null && paths.length != 0) {  

        String[] javaLibPath = paths;  

        int arr$ = paths.length;  

  

        int len$;  

        String path;  

        for(len$ = 0; len$ arr$; ++len$) {  

            String i$ = javaLibPath[len$];  

            path = (new File(i$)).getName();  

            if(loaded.contains(path)) {  

                log.info("already loaded " + i$);  

                return;  

            }  

        }  

  

        javaLibPath = System.getProperty("java.library.path").split(File.pathSeparator);//这里获得windows下path对应的路径,是个字符串数组  

        String[] var11 = paths;  

        len$ = paths.length;  

  

        for(int var12 = 0; var12 len$; ++var12) {  

            path = var11[var12];  

            log.config("JNI LIB = " + path);  

            String[] extracted = javaLibPath;  

            int len$1 = javaLibPath.length;  

  

            for(int i$1 = 0; i$1 len$1; ++i$1) {  

                String libPath = extracted[i$1];  

                File file = (new File(libPath, path)).getAbsoluteFile();//这里根据path路径和dll的名称拼成一个文件路径,下面检查这个文件是否存在,如果不存在,拼下一个文件路径,如果存在,就加载这个dll  

                log.finest("checking " + file);  

                if(file.exists() && file.isFile() && liberalLoad(file, path)) {  

                    return;  

                }  

            }  

  

            File var13 = extract(path);  

            if(var13 != null && liberalLoad(var13, path)) {  

                return;  

            }  

        }  

  

        throw new ExceptionInInitializerError("unable to load from " + Arrays.toString(paths));  

    } else {  

        throw new ExceptionInInitializerError("invalid parameters");  

    }  

}


其实这段代码本来我没有看太懂,但是架不住调试功能强大,运行一次,加断点,看看内容怎么变化,就知道是什么意思了.


这里假设我的windows下Path环境变量设置为:”D:\Python\Python35\Scripts\;D:\Program Files\Java\jdk1.7.0_15\bin;C:\WINDOWS;D:\BLAS;”,那么javaLibPath的内容就会是这四个组成的字符串数组.接下来取出来第一个,和dll名称(netlib-native_system-win-x86_64.dll)一起拼成一个文件路径”D:\Python\Python35\Scripts\netlib-native_system-win-x86_64.dll”,接下来检查这个路径是否是文件,如果不是,就会继续拼下一个,直到拼出”D:\BLAS\netlib-native_system-win-x86_64.dll”,然后我的dll文件确实放在这里,程序就会加载.


现在我们找到对应的dll文件,这里为netlib-native_system-win-x86_64.dll,然后放在D:\BLAS\这个位置,把D:\BLAS加入path变量,然后重启Intellij(这一步不一定需要,大家自己尝试),让它重新读取path值.


重新运行下Test里的main函数,然后运行结果竟然还是如上的错误,额,是我们刚才的分析都是错误了么?


2.dll库的依赖和依赖查找


我们在跳进加载dll的地方,看看究竟是哪里错了:


private static boolean liberalLoad(File file, String name) {  

        try {  

            log.finest("attempting to load " + file);  

            System.load(file.getAbsolutePath());  

            log.info("successfully loaded " + file);  

            loaded.add(name);  

            return true;  

        } catch (UnsatisfiedLinkError var6) {  

//这里捕获到一个异常,说Can't find dependent libraries.  

        log.log(Level.FINE, "skipping load of " + file, var6);  

        String tmpdir = System.getProperty("java.io.tmpdir");  

        if(tmpdir != null && tmpdir.trim().length() > 2 && file.getAbsolutePath().startsWith(tmpdir)) {  

            log.log(Level.FINE, "deleting " + file);  

  

            try {  

                file.delete();  

            } catch (Exception var5) {  

                log.info("failed to delete " + file);  

            }  

        }  

  

        return false;  

    } catch (SecurityException var7) {  

        log.log(Level.INFO, "skipping load of " + file, var7);  

        return false;  

    } catch (Throwable var8) {  

        throw new ExceptionInInitializerError(var8);  

    }  

}


这里我们捕获到一个异常,说 D:\BLAS\netlib-native_system-win-x86_64.dll: Can’t find dependent libraries.


原来如此我们的库还需要一些依赖库,这些依赖库没有找到.但是我们怎么知道这个库依赖于哪些库呢?哪些是已经有的,哪些是没有的?这里推荐一个工具,叫PEStudio,可以查看dll文件或exe文件依赖于哪些库:



这里显示了netlib-native_system-win-x86_64.dll依赖于哪些库,其中liblapack3.dll和libblas3.dll是我们需要找到了.其实到这一步,问题就算解决了,参见OpenBlas的官网,这些文件都可以很轻松的下载到,就是要注意首先需要知道你要的是32位还是64位,其次所有dll需要是统一的,不能部分32,部分64. 谢谢曲奇饼的提醒, 这里需要注意的还有jdk的版本, 在64位系统下, 应该使用64的jdk, 大家注意尝试.


这里是我用PEStudio找到的依赖关系:



至此,问题圆满解决.


=========================


最后,把在win10 64位系统下成功运行的库文件放在这:


csdn:http://download.csdn.net/detail/u201011221/9355487


baiduyun: http://pan.baidu.com/s/1jGO5waE


 关注「安卓开发精选
看更多精选安卓技术文章
↓↓↓