最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別

 更新時間:2021年05月11日 10:19:29   作者:gaussrieman123  
這篇文章主要介紹了java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

背景

近期要將算法部署到一個機群的虛擬主機(Debian 9.1 gcc 6.3.0)上,采用的是Java + JNI + shared library的方式來完成底層算法能力的部署。

其中需要用到各種第三方庫,有從源碼編譯的,也有直接下載的so,包括OpenCV相關、TensorFlow相關、MKL以OpenMP相關的動態(tài)庫。

遇到一個問題,libmklml_intel.so 這個庫只能放在 LD_LIBRARY_PATH中進行加載,而不能通過java.library.path完成加載,所以有必要搞清楚這兩個路徑究竟有什么區(qū)別。

java.library.path

官方文檔的定義是:List of paths to search when loading libraries
從定義我們可以發(fā)現(xiàn),首先是一個list,也就是說可以包括多個地址,然后這些地址是用來幫助jvm搜索需要加載的庫文件的。

設置java.library.path

最簡單的辦法就是在啟動jvm前通過java -Djava.library.path=path-to-your-libs設置這個全局變量。

作用

那么這個地址具體是如何被使用的呢?
當我們調用System.loadLibrary(libname)時,會調用Runtime.loadLibary,然后調用java/lang/ClassLoader.loadLibrary。在ClassLoader.loadLibrary中,系統(tǒng)屬性java.library.path將會被獲取,并用來生成需要加載的庫的絕對路徑,然后將這個絕對路徑傳給本地方法來調用dlopen/dlsym并最終加載這個庫。
如果加載失敗,會根據實際情況返回三個異常值:

SecurityException − if a security manager exists and its checkLink method doesn't allow loading of the specified dynamic library
UnsatisfiedLinkError − if the library does not exist
NullPointerException − if libname is null

可以參考OpenJDK的倉庫:

static void loadLibrary(Class fromClass, String name,
                            boolean isAbsolute) {
        ClassLoader loader =
            (fromClass == null) ? null : fromClass.getClassLoader();
        if (sys_paths == null) {
            usr_paths = initializePath("java.library.path");
            sys_paths = initializePath("sun.boot.library.path");
        }
        if (isAbsolute) {
            if (loadLibrary0(fromClass, new File(name))) {
                return;
            }
            throw new UnsatisfiedLinkError("Can't load library: " + name);
        }
        if (loader != null) {
            String libfilename = loader.findLibrary(name);
            if (libfilename != null) {
                File libfile = new File(libfilename);
                if (!libfile.isAbsolute()) {
                    throw new UnsatisfiedLinkError(
    "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
                }
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
                throw new UnsatisfiedLinkError("Can't load " + libfilename);
            }
        }
        for (int i = 0 ; i < sys_paths.length ; i++) {
            File libfile = new File(sys_paths[i], System.mapLibraryName(name));
            if (loadLibrary0(fromClass, libfile)) {
                return;
            }
        }
        if (loader != null) {
            for (int i = 0 ; i < usr_paths.length ; i++) {
                File libfile = new File(usr_paths[i],
                                        System.mapLibraryName(name));
                if (loadLibrary0(fromClass, libfile)) {
                    return;
                }
            }
        }
        // Oops, it failed
        throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
    }

LD_LIBRARY_PATH

為了搞清楚這個變量的作用,我們先說明一下Unix系統(tǒng)是如何加載動態(tài)庫的,然后自然就明白為什么要有LD_LIBRARY_PATH以及如何使用了。

動態(tài)庫如何加載?

在基于GNU glibc的系統(tǒng)上,包括所有的linux系統(tǒng),啟動一個ELF格式的二進制可執(zhí)行文件會自動調用加載器加載必要的動態(tài)鏈接庫,一個最簡單的可執(zhí)行文件一般也會包含一些系統(tǒng)的動態(tài)庫比如libc.so等。在Linux系統(tǒng)中,這個加載器叫做/lib/ld-linux.so.X,這個X指的是加載器的版本號。加載器然后查找并加載所需的動態(tài)庫。

加載器在什么路徑中搜索和加載動態(tài)庫呢——/etc/ld.so.conf,這個文件會包括/etc/ld.so.conf.d/*.conf這些文件夾中所有的.conf文件,而具體的動態(tài)庫搜索路徑,就包含在每個.conf文件中,比如/etc/ld.so.conf.d/libc.conf,它是libc的默認的搜索路徑/usr/local/lib,這也是為什么我們不需要顯示聲明使用系統(tǒng)庫卻能自動完成加載的原因,也是為什么不同的系統(tǒng)編出來的庫無法通用的可見原因之一,因為不同系統(tǒng)的/usr/local/lib目錄下的動態(tài)庫并不一致。

如果每次啟動都去查找所有的目錄,那樣顯然是比較笨的做法,所以使用/etc/ld.so.cache來緩存路徑,并通過ldconfig來更新這個緩存路徑,有興趣的可以自行查看一下這個緩存文件。實際上,這個緩存路徑也很長了,基本上包含了系統(tǒng)可能存放動態(tài)庫的路徑。

為什么有LD_LIBRARY_PATH?

上面我們說到可以通過cache和ldconfig來簡化搜索和加載動態(tài)庫的流程,但是還有兩個問題沒有考慮到,一是還沒有將編出來的庫放到系統(tǒng)目錄中去,二是依賴庫數(shù)量很少,不需要經過這么復雜的查找。

LD_LIBRARY_PATH就是用來滿足這個需要,它也指定一個搜索路徑,且ld-linux.so會優(yōu)先在這個路徑下搜索需要的動態(tài)庫,如果沒找到,再去ld.so.conf中指定的目錄尋找。

使用

export LD_LIBRARY_PATH=paths-to-libs

需要注意的一點是,多個目錄是通過:隔開的

區(qū)別

前面分別介紹了java.library.path 和 LD_LIBRARY_PATH,都是為了加載所需的動態(tài)庫,有什么區(qū)別呢?

前者是在java環(huán)境中調用,在jvm啟動前設置生效;后者也是在啟動前,但是是在Unix環(huán)境中使用前者是通過修改property來設置路徑;后者是直接增加了ld-linux.so的搜索路徑對于JNI直接調用的庫,最好使用前者,對于有多重依賴關系的庫,最好使用LD_LIBRARY_PATH

參考

HowTo: How to configure library path for JNI dependent libraries
https://zauner.nllk.net/post/0013-jni-and-the-java-library-path/
https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getProperties–
https://www.tutorialspoint.com/java/lang/runtime_loadlibrary.htm
https://stackoverflow.com/questions/27945268/difference-between-using-java-library-path-and-ld-library-path
Linux關于動態(tài)庫的文檔

到此這篇關于解析java.library.path和LD_LIBRARY_PATH的介紹與區(qū)別的文章就介紹到這了,更多相關java.library.path和LD_LIBRARY_PATH內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • java遍歷Map的幾種方法分析

    java遍歷Map的幾種方法分析

    這篇文章主要介紹了java遍歷Map的幾種方法,結合實例形式分析了使用循環(huán)與迭代等方法操作Map遍歷的相關技巧,需要的朋友可以參考下
    2016-08-08
  • 使用Intellij IDEA查看Java源碼技巧

    使用Intellij IDEA查看Java源碼技巧

    這篇文章主要介紹了使用Intellij IDEA查看Java源碼技巧,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java基于分治法實現(xiàn)的快速排序算法示例

    Java基于分治法實現(xiàn)的快速排序算法示例

    這篇文章主要介紹了Java基于分治法實現(xiàn)的快速排序算法,結合實例形式分析了java基于分治法的快速排序相關實現(xiàn)技巧,代碼中備有較為詳細的注釋說明便于理解,需要的朋友可以參考下
    2017-12-12
  • Java設計模式之外觀模式

    Java設計模式之外觀模式

    這篇文章介紹了Java設計模式之外觀模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • SpringBoot實現(xiàn)定時任務動態(tài)管理示例

    SpringBoot實現(xiàn)定時任務動態(tài)管理示例

    這篇文章主要為大家介紹了SpringBoot實現(xiàn)定時任務動態(tài)管理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Java之策略模式比較器案例講解

    Java之策略模式比較器案例講解

    這篇文章主要介紹了Java之策略模式比較器案例講解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08
  • java無限遞歸遍歷json對象問題

    java無限遞歸遍歷json對象問題

    這篇文章主要介紹了java無限遞歸遍歷json對象問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • springboot使用ThreadPoolTaskExecutor多線程批量插入百萬級數(shù)據的實現(xiàn)方法

    springboot使用ThreadPoolTaskExecutor多線程批量插入百萬級數(shù)據的實現(xiàn)方法

    這篇文章主要介紹了springboot利用ThreadPoolTaskExecutor多線程批量插入百萬級數(shù)據,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-02-02
  • Java如何用一個統(tǒng)一結構接收成員名稱不固定的數(shù)據

    Java如何用一個統(tǒng)一結構接收成員名稱不固定的數(shù)據

    這篇文章主要為大家詳細介紹了Java如何用一個統(tǒng)一結構接收成員名稱不固定的數(shù)據,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-11-11
  • Java Fork/Join框架

    Java Fork/Join框架

    Fork/Join框架是Java7中新增的一項特性,也是Java7平臺的其中一項主要改進。下面我們就來簡單探討下Java的Fork/Join框架
    2016-09-09

最新評論

晋城| 吉林省| 逊克县| 淮南市| 金阳县| 博湖县| 阿克陶县| 金溪县| 简阳市| 夹江县| 陈巴尔虎旗| 新安县| 会昌县| 来凤县| 金寨县| 永春县| 喀喇沁旗| 兰溪市| 神池县| 陆河县| 临安市| 河东区| 永德县| 黎城县| 赤水市| 双柏县| 珲春市| 克拉玛依市| 河北区| 靖江市| 大荔县| 固镇县| 黔江区| 民丰县| 德安县| 改则县| 天镇县| 黑山县| 固镇县| 定南县| 清远市|