您好,登錄后才能下訂單哦!
本篇文章為大家展示了在android中怎么用Java加載解析so,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
so的加載是一種解析式裝載,這與dex有一定區(qū)別,dex是先加載進(jìn)行優(yōu)化驗(yàn)證生成odex,再去解析odex文件,而so更像邊解析邊裝載,在加載過(guò)程中主要解析是load段。
下面主要是以java層的so加載進(jìn)行從源碼上進(jìn)行解析加載流程。
在java層我們知道加載so文件是通過(guò)System.loadLibrary函數(shù)其實(shí)現(xiàn)的,下面就以其作為入口點(diǎn)進(jìn)行分析它的調(diào)用關(guān)系和實(shí)現(xiàn)。
System.loadLibrary在的函數(shù)定義系統(tǒng)source\libcore\luni\src\main\java\java\lang\system.java的文件中。
下面是其函數(shù)定義實(shí)現(xiàn)。
//參數(shù)就是要加載的so文件名稱 public static void loadLibrary(String libName) { //通過(guò)調(diào)用Runtime下面的loadLibrary函數(shù)實(shí)現(xiàn) //函數(shù)有兩個(gè)參數(shù),參數(shù)1是加載的so文件名,參數(shù)2 類加載器。 Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); }
通過(guò)上面的System.java的loadLibrary函數(shù)我們需要繼續(xù)分析Runtime.java文件中的loadLibray函數(shù)的定義實(shí)現(xiàn)。
Runtime的loadLibrary函數(shù)在android系統(tǒng)中的位置是
source\libcore\luni\src\main\java\java\lang\Runtime.java文件。
下面是Runtime的 loadLibrary函數(shù)的定義實(shí)現(xiàn)源碼。
/* * Searches for and loads the given shared library using the given ClassLoader. */ void loadLibrary(String libraryName, ClassLoader loader) { if (loader != null) { //通過(guò)加載器去查找要加載的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; //循環(huán)遍歷文件路徑 for (String directory : mLibPaths) { //文件路徑和文件名進(jìn)行拼接 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); }
通過(guò)上面的Runtime的loadLibrary函數(shù),我們看到加載so的函數(shù)是走到doLoad函數(shù),那么我們就需要繼續(xù)分析Runtime下的doload函數(shù)的定義實(shí)現(xiàn)。
Rutime下的doload函數(shù)在系統(tǒng)中的
source\libcore\luni\src\main\java\java\lang\Runtime.java文件中。
下面的代碼是Runtime的doload函數(shù)的定義實(shí)現(xiàn)。
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); } }
從以上的源碼實(shí)現(xiàn)流程分析,我們可以看出Android在java層加載so的接口是System.loadLibrary(),通過(guò)層層遞進(jìn)關(guān)系從而實(shí)現(xiàn)java層的加載so。
上述內(nèi)容就是在android中怎么用Java加載解析so,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(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)容。