各安卓版本关于loadLibrary函数的实现区别(Implementation differences of loadlibrary function in Android versions)

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);

this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

private static File[] splitLibraryPath(String path)

private static File[] splitLibraryPath(String path)

6.0

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

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)

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);

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

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

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

8.0 ~ 8.1

this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

private static NativeLibraryElement[] makePathElements(List files)

private static NativeLibraryElement[] makePathElements(List files)

————————

Loadlibrary is mainly used in runtime Implemented in Java, there are great differences between different versions, so take a note to sort out these differences.

Version 4.4

Source code:

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

Mainly this one:

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    }

A key part of the code is this:

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            }

Then look for 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    }

This is to traverse the nativelibrarydirectories variable to see if it contains the so file to be loaded.

Let’s see how native library directories are obtained.

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

It’s a file [] array, and it’s final.

But then, when dexpathlist is initialized, assign this variable:

  • this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

Version 5.0

Source code:

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;

It is also a file array and is final.

The final assignment is the same as 4.4:

  • this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

Version 5.1

Source code:

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)

Version 6.0

Source code:

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;

Copy from here

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

然后makePathElements:

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

Property is OK.

Version 7.0

Source code:

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

The function loadlibrary0 has been added since 7.0. In fact, it changes the previous loadlibrary to this function. In fact, it has one function

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;

How to assign values:

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

Changed again

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

The two lists and a file in 6.0 have been changed to two lists and a classloader

7.1 is the same as 7.0 and will not be repeated.

eight

Source code:

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    }

How do you assign values

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

然后makePathElements:

  • private static NativeLibraryElement[] makePathElements(List files)

The return value and parameters have been changed.

I wonder why Google people do nothing to change this all day. Is there a loophole?

summary

4.4 ~5.1

Are used

this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

this.nativeLibraryDirectories = splitLibraryPath(libraryPath);

private static File[] splitLibraryPath(String path)

private static File[] splitLibraryPath(String path)

six

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

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)

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);

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

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

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

8.0 ~ 8.1

this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);

private static NativeLibraryElement[] makePathElements(List files)

private static NativeLibraryElement[] makePathElements(List files)