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

  • 相关阅读:
    忙活了半宿,写了个小玩意
    luogu P5171 Earthquake
    luogu P1850 换教室
    luogu P2507 [SCOI2008]配对 |动态规划
    luogu P3830 [SHOI2012]随机树
    luogu P3959 宝藏
    牛客竞赛-比赛
    牛客竞赛-Who killed Cock Robin
    luogu P3807 【模板】卢卡斯定理
    牛客竞赛 -被3整除的子序列
  • 原文地址:https://www.cnblogs.com/Tu9oh0st/p/15801755.html
Copyright © 2020-2023  润新知