本次代码主要想解决DexClassLoader出现ClassNotFound问题,实际上没有解决。但毕竟是自己第一次写的ClassLoader。这里记录一下。
/**
* DexClassLoader may cause ClassNotFound because of caching wrong DexInfo in
* some cases
*
* To avoid the caching problem. This class will try to reCreate DexClassLoader
* and call loadClass again to solve the issue.
*
* @author zhenhuachen
*/
final class RetryDexClassLoader extends DexClassLoader {
private String mDexPath;
private String mOptimizedDirectory;
private String mLibraryPath;
private ClassLoader mParent;
private DexClassLoader mSecondRecoveryClassLoader;
private ArrayList<ClassLoader> mCreatedClassLoaderList = new ArrayList<ClassLoader>();
/**
* map of class.
*/
private final ConcurrentHashMap<String, Class<?>> mClassMap = new ConcurrentHashMap<String, Class<?>>();
public RetryDexClassLoader(String dexPath, String optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(dexPath, optimizedDirectory, libraryPath, parent);
mDexPath = dexPath;
mOptimizedDirectory = optimizedDirectory;
mLibraryPath = libraryPath;
mParent = parent;
mCreatedClassLoaderList.add(parent);
}
private void createRealClassLoader() {
MultiParentClassLoader parentLoader = new MultiParentClassLoader();
parentLoader.addParent(mCreatedClassLoaderList);
mSecondRecoveryClassLoader = new DexClassLoader(mDexPath,
mOptimizedDirectory, mLibraryPath, parentLoader);
mCreatedClassLoaderList.add(mSecondRecoveryClassLoader);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> clazz = mClassMap.get(name);
if (null != clazz) {
return clazz;
}
try {
clazz = mParent.loadClass(name);
} catch (ClassNotFoundException e) {
try {
clazz = findClass(name);
} catch (ClassNotFoundException e1) {
createRealClassLoader();
clazz = mSecondRecoveryClassLoader.loadClass(name);
}
}
if (null == clazz) {
throw new ClassNotFoundException("Didn't find class \"" + name);
} else {
mClassMap.put(name, clazz);
}
return clazz;
}
}
final class MultiParentClassLoader extends ClassLoader{
private ArrayList<ClassLoader> mParentLoaderList = new ArrayList<ClassLoader>();
public MultiParentClassLoader() {
}
@Override
public Class<?> loadClass(String className) throws ClassNotFoundException {
Class<?> clazz = null;
for (ClassLoader loader : mParentLoaderList) {
try{
clazz = loader.loadClass(className);
} catch(ClassNotFoundException e) {
Log.d("MultiParentClassLoader", "loadClass");
}
}
if (null != clazz) {
Log.d("MultiParentClassLoader", "loadClass found in mParentLoaderList");
}
return clazz;
}
public void addParent(ClassLoader loader) {
mParentLoaderList.add(loader);
}
public void addParent(ArrayList<ClassLoader> loaderList) {
mParentLoaderList.addAll(loaderList);
}
}