首先跟着源码走
System.loadLibrary(“native-lib”)
在loadLibrary里面会调用Runtime.getRuntime().loadLibrary0()方法,里面有两个参数VMStack.getCallingClassLoader()和libname
Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), libname);
继续在Runtime类中会找到loadLibrary0方法
synchronized void loadLibrary0(ClassLoader loader, String libname) {
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError(
"Directory separator should not appear in library name: " + libname);
}
String libraryName = libname;
if (loader != null) {
String filename = loader.findLibrary(libraryName);
if (filename == null) {
// It's not necessarily true that the ClassLoader used
// System.mapLibraryName, but the default setup does, and it's
// misleading to say we didn't find "libMyLibrary.so" when we
// actually searched for "liblibMyLibrary.so.so".
throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
System.mapLibraryName(libraryName) + "\"");
}
String error = doLoad(filename, loader);
if (error != null) {
throw new UnsatisfiedLinkError(error);
}
return;
}
String filename = System.mapLibraryName(libraryName);
List<String> candidates = new ArrayList<String>();
String lastError = null;
for (String directory : getLibPaths()) {
String candidate = directory + filename;
candidates.add(candidate);
if (IoUtils.canOpenReadOnly(candidate)) {
String error = doLoad(candidate, loader);
if (error == null) {
return; // We successfully loaded the library. Job done.
}
lastError = error;
}
}
if (lastError != null) {
throw new UnsatisfiedLinkError(lastError);
}
throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates);
}
这里面有个判断,判断ClassLoader在不在,一般都是有的所以会进入,这里面有个重要 的方法 loader.findLibrary(libraryName);当我们点进去的时候发现返回的是NULL
protected String findLibrary(String libname) {
return null;
}
这样我们就想到了,他还会有子类于是我们通过LOG打印出当前的ClassLoader
Log.d(TAG,"ClassLoader ++"+this.getClassLoader().toString());
// 这是打印的子类dalvik.system.PathClassLoader
于是我们翻看Android源码7.1.1(有5.23个G已下载好)PathClassLoader类,发现没有实现太多。于是我们找到了他的父类BaseDexClassLoader的findLibrary()方法
他这里面返回了pathList.findLibrary(name)
@Override
public String findLisbrary(String name){
return pathList.findLibrary(name);
}
本文详细解析了Java调用So库的具体流程,从System.loadLibrary方法开始,深入到Runtime类中的loadLibrary0方法,解释了ClassLoader如何查找并加载本地库文件。并通过Android平台上的BaseDexClassLoader类说明了库文件查找的具体实现。
3271

被折叠的 条评论
为什么被折叠?



