各安卓版本关于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)

上一篇:动手学PyG(三):PyG中的mini-batches


下一篇:Vue学习笔记---webpack概念