各安卓版本關於loadLibrary函數的實現區別

loadLibrary主要是在Runtime.java中實現,各個版本之間差異比較大,所以做個筆記來整理這些區別。

4.4 版本

源碼:

Cross Reference: /libcore/luni/src/main/java/java/lang/Runtime.java

主要是這一塊:

http://androidxref.com/4.4.4_r1/xref/libcore/luni/src/main/java/java/lang/Runtime.java#354

void loadLibrary(String libraryName, ClassLoader loader) {
355        if (loader != null) {
356            String filename = loader.findLibrary(libraryName);
357            if (filename == null) {
358                throw new UnsatisfiedLinkError("Couldn't load " + libraryName +
359                                               " from loader " + loader +
360                                               ": findLibrary returned null");
361            }
362            String error = doLoad(filename, loader);
363            if (error != null) {
364                throw new UnsatisfiedLinkError(error);
365            }
366            return;
367        }
368
369        String filename = System.mapLibraryName(libraryName);
370        List<String> candidates = new ArrayList<String>();
371        String lastError = null;
372        for (String directory : mLibPaths) {
373            String candidate = directory + filename;
374            candidates.add(candidate);
375
376            if (IoUtils.canOpenReadOnly(candidate)) {
377                String error = doLoad(candidate, loader);
378                if (error == null) {
379                    return; // We successfully loaded the library. Job done.
380                }
381                lastError = error;
382            }
383        }
384
385        if (lastError != null) {
386            throw new UnsatisfiedLinkError(lastError);
387        }
388        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
389    }

其中關鍵的一部分代碼是這個:

String filename = loader.findLibrary(libraryName);
357            if (filename == null) {
358                throw new UnsatisfiedLinkError("Couldn't load " + libraryName +
359                                               " from loader " + loader +
360                                               ": findLibrary returned null");
361            }

接着去尋找findLibrary。

http://androidxref.com/4.4.4_r1/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java#380

380    public String findLibrary(String libraryName) {
381        String fileName = System.mapLibraryName(libraryName);
382        for (File directory : nativeLibraryDirectories) {
383            String path = new File(directory, fileName).getPath();
384            if (IoUtils.canOpenReadOnly(path)) {
385                return path;
386            }
387        }
388        return null;
389    }

就是將nativeLibraryDirectories變量遍歷裏面是否包含了要加載的so文件。

來看下nativeLibraryDirectories是怎麼得到的。

/** List of native library directories. */
private final File[]nativeLibraryDirectories;

是一個File[]數組呢,而且是final的。

但是接着看的話,在DexPathList初始化的時候將這個變量進行賦值:

  • this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

5.0版本

源碼:

http://androidxref.com/5.0.0_r2/xref/libcore/luni/src/main/java/java/lang/Runtime.java

358    void loadLibrary(String libraryName, ClassLoader loader) {
359        if (loader != null) {
360            String filename = loader.findLibrary(libraryName);
361            if (filename == null) {
362                // It's not necessarily true that the ClassLoader used
363                // System.mapLibraryName, but the default setup does, and it's
364                // misleading to say we didn't find "libMyLibrary.so" when we
365                // actually searched for "liblibMyLibrary.so.so".
366                throw new UnsatisfiedLinkError(loader + " couldn't find \\"" +
367                                               System.mapLibraryName(libraryName) + "\\"");
368            }
369            String error = doLoad(filename, loader);
370            if (error != null) {
371                throw new UnsatisfiedLinkError(error);
372            }
373            return;
374        }
375
376        String filename = System.mapLibraryName(libraryName);
377        List<String> candidates = new ArrayList<String>();
378        String lastError = null;
379        for (String directory : mLibPaths) {
380            String candidate = directory + filename;
381            candidates.add(candidate);
382
383            if (IoUtils.canOpenReadOnly(candidate)) {
384                String error = doLoad(candidate, loader);
385                if (error == null) {
386                    return; // We successfully loaded the library. Job done.
387                }
388                lastError = error;
389            }
390        }
391
392        if (lastError != null) {
393            throw new UnsatisfiedLinkError(lastError);
394        }
395        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
396    }

findLibrary:

379    public String findLibrary(String libraryName) {
380        String fileName = System.mapLibraryName(libraryName);
381        for (File directory : nativeLibraryDirectories) {
382            String path = new File(directory, fileName).getPath();
383            if (IoUtils.canOpenReadOnly(path)) {
384                return path;
385            }
386        }
387        return null;
388    }

nativeLibraryDirectories:

/** List of native library directories. */
private final File[]nativeLibraryDirectories;

也還是File數組且爲final。

最後賦值也是跟4.4一樣:

  • this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

5.1版本

源碼:

http://androidxref.com/5.1.1_r6/xref/libcore/luni/src/main/java/java/lang/Runtime.java

358    void loadLibrary(String libraryName, ClassLoader loader) {
359        if (loader != null) {
360            String filename = loader.findLibrary(libraryName);
361            if (filename == null) {
362                // It's not necessarily true that the ClassLoader used
363                // System.mapLibraryName, but the default setup does, and it's
364                // misleading to say we didn't find "libMyLibrary.so" when we
365                // actually searched for "liblibMyLibrary.so.so".
366                throw new UnsatisfiedLinkError(loader + " couldn't find \\"" +
367                                               System.mapLibraryName(libraryName) + "\\"");
368            }
369            String error = doLoad(filename, loader);
370            if (error != null) {
371                throw new UnsatisfiedLinkError(error);
372            }
373            return;
374        }
375
376        String filename = System.mapLibraryName(libraryName);
377        List<String> candidates = new ArrayList<String>();
378        String lastError = null;
379        for (String directory : mLibPaths) {
380            String candidate = directory + filename;
381            candidates.add(candidate);
382
383            if (IoUtils.canOpenReadOnly(candidate)) {
384                String error = doLoad(candidate, loader);
385                if (error == null) {
386                    return; // We successfully loaded the library. Job done.
387                }
388                lastError = error;
389            }
390        }
391
392        if (lastError != null) {
393            throw new UnsatisfiedLinkError(lastError);
394        }
395        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
396    }

findLibrary:

379    public String findLibrary(String libraryName) {
380        String fileName = System.mapLibraryName(libraryName);
381        for (File directory : nativeLibraryDirectories) {
382            String path = new File(directory, fileName).getPath();
383            if (IoUtils.canOpenReadOnly(path)) {
384                return path;
385            }
386        }
387        return null;
388    }

nativeLibraryDirectories:

/** List of native library directories. */
private final File[] nativeLibraryDirectories;
  • this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
  • private static File[] splitLibraryPath(String path)

6.0版本

源碼:

http://androidxref.com/6.0.1_r10/xref/libcore/luni/src/main/java/java/lang/Runtime.java

359    void loadLibrary(String libraryName, ClassLoader loader) {
360        if (loader != null) {
361            String filename = loader.findLibrary(libraryName);
362            if (filename == null) {
363                // It's not necessarily true that the ClassLoader used
364                // System.mapLibraryName, but the default setup does, and it's
365                // misleading to say we didn't find "libMyLibrary.so" when we
366                // actually searched for "liblibMyLibrary.so.so".
367                throw new UnsatisfiedLinkError(loader + " couldn't find \\"" +
368                                               System.mapLibraryName(libraryName) + "\\"");
369            }
370            String error = doLoad(filename, loader);
371            if (error != null) {
372                throw new UnsatisfiedLinkError(error);
373            }
374            return;
375        }
376
377        String filename = System.mapLibraryName(libraryName);
378        List<String> candidates = new ArrayList<String>();
379        String lastError = null;
380        for (String directory : mLibPaths) {
381            String candidate = directory + filename;
382            candidates.add(candidate);
383
384            if (IoUtils.canOpenReadOnly(candidate)) {
385                String error = doLoad(candidate, loader);
386                if (error == null) {
387                    return; // We successfully loaded the library. Job done.
388                }
389                lastError = error;
390            }
391        }
392
393        if (lastError != null) {
394            throw new UnsatisfiedLinkError(lastError);
395        }
396        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
397    }

findLibrary:

396    public String findLibrary(String libraryName) {
397        String fileName = System.mapLibraryName(libraryName);
398
399        for (Element element : nativeLibraryPathElements) {
400            String path = element.findNativeLibrary(fileName);
401
402            if (path != null) {
403                return path;
404            }
405        }
406
407        return null;
408    }

nativeLibraryPathElements,從6.0開始好像就有了nativeLibraryPathElements這個屬性。

/** List of native library path elements. */
private final Element[] nativeLibraryPathElements;

從這裏開始複製

this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,
                                                      suppressedExceptions);

然後makePathElements:

private static Element[] makePathElements(List<File>files,File optimizedDirectory,List<IOException>suppressedExceptions)

屬性就可以了。

7.0版本

源碼:

http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/java/java/lang/Runtime.java

從7.0開始增加了loadLibrary0這個函數,其實就是將之前的loadLibrary改成了這個,其實都一個作用

959    synchronized void loadLibrary0(ClassLoader loader, String libname) {
960        if (libname.indexOf((int)File.separatorChar) != -1) {
961            throw new UnsatisfiedLinkError(
962    "Directory separator should not appear in library name: " + libname);
963        }
964        String libraryName = libname;
965        if (loader != null) {
966            String filename = loader.findLibrary(libraryName);
967            if (filename == null) {
968                // It's not necessarily true that the ClassLoader used
969                // System.mapLibraryName, but the default setup does, and it's
970                // misleading to say we didn't find "libMyLibrary.so" when we
971                // actually searched for "liblibMyLibrary.so.so".
972                throw new UnsatisfiedLinkError(loader + " couldn't find \\"" +
973                                               System.mapLibraryName(libraryName) + "\\"");
974            }
975            String error = doLoad(filename, loader);
976            if (error != null) {
977                throw new UnsatisfiedLinkError(error);
978            }
979            return;
980        }
981
982        String filename = System.mapLibraryName(libraryName);
983        List<String> candidates = new ArrayList<String>();
984        String lastError = null;
985        for (String directory : getLibPaths()) {
986            String candidate = directory + filename;
987            candidates.add(candidate);
988
989            if (IoUtils.canOpenReadOnly(candidate)) {
990                String error = doLoad(candidate, loader);
991                if (error == null) {
992                    return; // We successfully loaded the library. Job done.
993                }
994                lastError = error;
995            }
996        }
997
998        if (lastError != null) {
999            throw new UnsatisfiedLinkError(lastError);
1000        }
1001        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
1002    }

findLibrary:

476    public String findLibrary(String libraryName) {
477        String fileName = System.mapLibraryName(libraryName);
478
479        for (Element element : nativeLibraryPathElements) {
480            String path = element.findNativeLibrary(fileName);
481
482            if (path != null) {
483                return path;
484            }
485        }
486
487        return null;
488    }

nativeLibraryPathElements:

/** List of native library path elements. */
private final Element[]nativeLibraryPathElements;

怎麼賦值的呢:

145        this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories,
146                                                          suppressedExceptions,
147                                                          definingContext);

又進行了改變

269    private static Element[] makePathElements(List<File> files,
270                                              List<IOException> suppressedExceptions,
271                                              ClassLoader loader)

之前6.0的兩個list和一個file,又改成了兩個list和一個classloader

7.1跟7.0一樣不贅述。

8.0

源碼:

http://androidxref.com/8.1.0_r33/xref/libcore/ojluni/src/main/java/java/lang/Runtime.java

998    synchronized void loadLibrary0(ClassLoader loader, String libname) {
999        if (libname.indexOf((int)File.separatorChar) != -1) {
1000            throw new UnsatisfiedLinkError(
1001    "Directory separator should not appear in library name: " + libname);
1002        }
1003        String libraryName = libname;
1004        if (loader != null) {
1005            String filename = loader.findLibrary(libraryName);
1006            if (filename == null) {
1007                // It's not necessarily true that the ClassLoader used
1008                // System.mapLibraryName, but the default setup does, and it's
1009                // misleading to say we didn't find "libMyLibrary.so" when we
1010                // actually searched for "liblibMyLibrary.so.so".
1011                throw new UnsatisfiedLinkError(loader + " couldn't find \\"" +
1012                                               System.mapLibraryName(libraryName) + "\\"");
1013            }
1014            String error = doLoad(filename, loader);
1015            if (error != null) {
1016                throw new UnsatisfiedLinkError(error);
1017            }
1018            return;
1019        }
1020
1021        String filename = System.mapLibraryName(libraryName);
1022        List<String> candidates = new ArrayList<String>();
1023        String lastError = null;
1024        for (String directory : getLibPaths()) {
1025            String candidate = directory + filename;
1026            candidates.add(candidate);
1027
1028            if (IoUtils.canOpenReadOnly(candidate)) {
1029                String error = doLoad(candidate, loader);
1030                if (error == null) {
1031                    return; // We successfully loaded the library. Job done.
1032                }
1033                lastError = error;
1034            }
1035        }
1036
1037        if (lastError != null) {
1038            throw new UnsatisfiedLinkError(lastError);
1039        }
1040        throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
1041    }

findLibrary:

524    public String findLibrary(String libraryName) {
525        String fileName = System.mapLibraryName(libraryName);
526
527        for (NativeLibraryElement element : nativeLibraryPathElements) {
528            String path = element.findNativeLibrary(fileName);
529
530            if (path != null) {
531                return path;
532            }
533        }
534
535        return null;
536    }

怎麼賦值的呢

  • this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

然後makePathElements:

  • private static NativeLibraryElement[] makePathElements(List files)

返回值改了,參數也改了。

就很納悶,google這幫人不幹實事整天改這個幹嘛,有漏洞?

總結

4.4 ~5.1

都是使用的

this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

private static File[] splitLibraryPath(String path)

6.0

this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,suppressedExceptions);

private static Element[] makePathElements(List[File](%5BFile%5D(http://androidxref.com/6.0.1_r10/s?defs=File&project=libcore)) files, File optimizedDirectory,List[IOException](%5BIOException%5D(http://androidxref.com/6.0.1_r10/s?defs=IOException&project=libcore)) suppressedExceptions)

7.0 ~ 7.1

this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, suppressedExceptions, definingContext);

private static Element[] makePathElements(List files, List suppressedExceptions, ClassLoader loader)

8.0 ~ 8.1

this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

private static NativeLibraryElement[] makePathElements(List files)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章