溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java中l(wèi)ibrary.path和LD_LIBRARY_PATH有什么區(qū)別

發(fā)布時(shí)間:2021-05-11 15:10:38 來(lái)源:億速云 閱讀:232 作者:Leah 欄目:開發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)java中l(wèi)ibrary.path和LD_LIBRARY_PATH有什么區(qū)別,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

java基本數(shù)據(jù)類型有哪些

Java的基本數(shù)據(jù)類型分為:1、整數(shù)類型,用來(lái)表示整數(shù)的數(shù)據(jù)類型。2、浮點(diǎn)類型,用來(lái)表示小數(shù)的數(shù)據(jù)類型。3、字符類型,字符類型的關(guān)鍵字是“char”。4、布爾類型,是表示邏輯值的基本數(shù)據(jù)類型。

java.library.path

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

設(shè)置java.library.path

最簡(jiǎn)單的辦法就是在啟動(dòng)jvm前通過(guò)java -Djava.library.path=path-to-your-libs設(shè)置這個(gè)全局變量。

作用

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

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的倉(cāng)庫(kù):

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

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

動(dòng)態(tài)庫(kù)如何加載?

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

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

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

為什么有LD_LIBRARY_PATH?

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

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

使用

export LD_LIBRARY_PATH=paths-to-libs

需要注意的一點(diǎn)是,多個(gè)目錄是通過(guò):隔開的

區(qū)別

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

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

上述就是小編為大家分享的java中l(wèi)ibrary.path和LD_LIBRARY_PATH有什么區(qū)別了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI