本文主要目的是搞清楚so加载和调用的整体脉络,以便遇到so相关的问题时做到心中有数,能迅速把握解决问题的大方向。
先抛出两个问题:
1. 退出插件时如何卸载so,以免内存占用越来越大?
2. 热修复中如何实现native函数的热替换?
这两个问题我会在文章结尾给出解决思路。
so是在System.loadLibrary中加载的,如下:
public static void loadLibrary(String libName) {
Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
}
这里传入的ClassLoader正是调用System.loadLibrary的类的ClassLoader,通常为PathClassLoader。
再来看Runtime.loadLibrary的实现:
void loadLibrary(String libraryName, ClassLoader loader) {
if (loader != null) {
String filename = loader.findLibrary(libraryName);
String error = nativeLoad(filename, loader);
return;
}
String filename = System.mapLibraryName(libraryName);
List<String> candidates = new ArrayList<String>();
String lastError = null;
for (String directory : mLibPaths) {
String candidate = directory + filename;
candidates.add(candidate);
if (new File(candidate).exists()) {
String error = nativeLoad(candidate, loader);
if (error == null) {
return;
}
lastError = error;
}
}
..........
}
这里主要做了两件事,首先去查找所有可能的路径判断so是否存在,如果存在就调用nativeLoad加载so。我们重点看so的加载:
static void Dalvik_java_lang_Runtime_nati