中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

在android中怎么用Java加載解析so

發布時間:2021-10-09 13:47:40 來源:億速云 閱讀:98 作者:柒染 欄目:開發技術

本篇文章為大家展示了在android中怎么用Java加載解析so,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

理論基礎

so的加載是一種解析式裝載,這與dex有一定區別,dex是先加載進行優化驗證生成odex,再去解析odex文件,而so更像邊解析邊裝載,在加載過程中主要解析是load段。
下面主要是以java層的so加載進行從源碼上進行解析加載流程。

java層的so加載流程分析

 System.loadLibrary入口點

在java層我們知道加載so文件是通過System.loadLibrary函數其實現的,下面就以其作為入口點進行分析它的調用關系和實現。
System.loadLibrary在的函數定義系統source\libcore\luni\src\main\java\java\lang\system.java的文件中。

下面是其函數定義實現。

//參數就是要加載的so文件名稱
 public static void loadLibrary(String libName) {
         //通過調用Runtime下面的loadLibrary函數實現
         //函數有兩個參數,參數1是加載的so文件名,參數2 類加載器。
        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
    }

Runtime的loadLibray解析

通過上面的System.java的loadLibrary函數我們需要繼續分析Runtime.java文件中的loadLibray函數的定義實現。
Runtime的loadLibrary函數在android系統中的位置是
source\libcore\luni\src\main\java\java\lang\Runtime.java文件。

下面是Runtime的 loadLibrary函數的定義實現源碼。

/*
     * Searches for and loads the given shared library using the given ClassLoader.
     */
    void loadLibrary(String libraryName, ClassLoader loader) {
        if (loader != null) {
            //通過加載器去查找要加載的so文件名
            String filename = loader.findLibrary(libraryName);
            //查找失敗
            if (filename == null) {
                // It's not necessarily true that the ClassLoader used
                // System.mapLibraryName, but the default setup does, and it's
                // misleading to say we didn't find "libMyLibrary.so" when we
                // actually searched for "liblibMyLibrary.so.so".
                throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
                                               System.mapLibraryName(libraryName) + "\"");
            }
            //加載so文件名
            String error = doLoad(filename, loader);
            if (error != null) {
                throw new UnsatisfiedLinkError(error);
            }
            return;
        }
        
        String filename = System.mapLibraryName(libraryName);
        List<String> candidates = new ArrayList<String>();
        String lastError = null;
        //循環遍歷文件路徑
        for (String directory : mLibPaths) {
            //文件路徑和文件名進行拼接
            String candidate = directory + filename;
            candidates.add(candidate);

            if (IoUtils.canOpenReadOnly(candidate)) {
                String error = doLoad(candidate, loader);
                if (error == null) {
                    return; // We successfully loaded the library. Job done.
                }
                lastError = error;
            }
        }

        if (lastError != null) {
            throw new UnsatisfiedLinkError(lastError);
        }
        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
    }

Runtime的doLoad解析

通過上面的Runtime的loadLibrary函數,我們看到加載so的函數是走到doLoad函數,那么我們就需要繼續分析Runtime下的doload函數的定義實現。
Rutime下的doload函數在系統中的
source\libcore\luni\src\main\java\java\lang\Runtime.java文件中。

下面的代碼是Runtime的doload函數的定義實現。

 private String doLoad(String name, ClassLoader loader) {
        // Android apps are forked from the zygote, so they can't have a custom LD_LIBRARY_PATH,
        // which means that by default an app's shared library directory isn't on LD_LIBRARY_PATH.

        // The PathClassLoader set up by frameworks/base knows the appropriate path, so we can load
        // libraries with no dependencies just fine, but an app that has multiple libraries that
        // depend on each other needed to load them in most-dependent-first order.

        // We added API to Android's dynamic linker so we can update the library path used for
        // the currently-running process. We pull the desired path out of the ClassLoader here
        // and pass it to nativeLoad so that it can call the private dynamic linker API.

        // We didn't just change frameworks/base to update the LD_LIBRARY_PATH once at the
        // beginning because multiple apks can run in the same process and third party code can
        // use its own BaseDexClassLoader.

        // We didn't just add a dlopen_with_custom_LD_LIBRARY_PATH call because we wanted any
        // dlopen(3) calls made from a .so's JNI_OnLoad to work too.

        // So, find out what the native library search path is for the ClassLoader in question...
        String ldLibraryPath = null;
        if (loader != null && loader instanceof BaseDexClassLoader) {
            ldLibraryPath = ((BaseDexClassLoader) loader).getLdLibraryPath();
        }
        // nativeLoad should be synchronized so there's only one LD_LIBRARY_PATH in use regardless
        // of how many ClassLoaders are in the system, but dalvik doesn't support synchronized
        // internal natives.
        synchronized (this) {
            return nativeLoad(name, loader, ldLibraryPath);
        }
    }

從以上的源碼實現流程分析,我們可以看出Android在java層加載so的接口是System.loadLibrary(),通過層層遞進關系從而實現java層的加載so。

上述內容就是在android中怎么用Java加載解析so,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

噶尔县| 雅安市| 昌吉市| 霍林郭勒市| 长岭县| 新巴尔虎右旗| 莆田市| 和政县| 揭阳市| 西贡区| 西华县| 渭源县| 公主岭市| 绥德县| 江西省| 漯河市| 两当县| 斗六市| 夏河县| 房产| 永和县| 凤台县| 莱西市| 嘉定区| 淮安市| 文水县| 宝坻区| 喀什市| 高青县| 融水| 大新县| 蛟河市| 汾阳市| 深水埗区| 凤凰县| 北安市| 普安县| 沛县| 台前县| 延川县| 正镶白旗|