ClassLoader原理剖析

来源:互联网 发布:win7旗舰版服务优化 编辑:程序博客网 时间:2024/06/05 00:44

ClassLoader原理剖析


Android 中 ClassLoader 种类

BootClassLoader

加载 Android FrameWork 层的class字节码文件

PathClassLoader

加载已经安装到系统中的apk 文件中的class 字节码文件

DexClassLoader

加载指定目录中的 class字节码文件

BaseClassLoader

是 PathClassLoader 和 DexClassLoader 的父类

Android 中 ClassLoader 的特点

  • 双亲代理模式的特点
  • 类加载的共享功能
  • 类加载的隔离功能

ClassLoader源码分析

protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {        //检测当前类是否被加载        Class<?> clazz = findLoadedClass(className);        if (clazz == null) {            ClassNotFoundException suppressed = null;            try {                clazz = parent.loadClass(className, false);            } catch (ClassNotFoundException e) {                suppressed = e;            }            if (clazz == null) {                try {                    clazz = findClass(className);                } catch (ClassNotFoundException e) {                    e.addSuppressed(suppressed);                    throw e;                }            }        }        return clazz;    }//空实现,交由子类去实现protected Class<?> findClass(String className) throws ClassNotFoundException {        throw new ClassNotFoundException(className);    }  // A class loader that loads classes from {@code .jar} and {@code .apk} files containing a {@code classes.dex} entry.//加载未安装到系统中的应用的类,动态加载的核心public class DexClassLoader extends BaseDexClassLoader {    public DexClassLoader(String dexPath, String optimizedDirectory,String libraryPath, ClassLoader parent) {       super(dexPath, new File(optimizedDirectory), libraryPath, parent);    }}//加载指定路径下的 class 文件 public class PathClassLoader extends BaseDexClassLoader {    public PathClassLoader(String dexPath, ClassLoader parent) {        super(dexPath, null, null, parent);    }    public PathClassLoader(String dexPath, String libraryPath,            ClassLoader parent) {        super(dexPath, null, libraryPath, parent);    }}public class BaseDexClassLoader extends ClassLoader {    private final DexPathList pathList;    public BaseDexClassLoader(String dexPath, File optimizedDirectory,            String libraryPath, ClassLoader parent) {        super(parent);        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);    }    @Override    protected Class<?> findClass(String name) throws ClassNotFoundException {        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();        Class c = pathList.findClass(name, suppressedExceptions);        if (c == null) {            ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);            for (Throwable t : suppressedExceptions) {                cnfe.addSuppressed(t);            }            throw cnfe;        }        return c;    }    @Override    protected URL findResource(String name) {        return pathList.findResource(name);    }    @Override    protected Enumeration<URL> findResources(String name) {        return pathList.findResources(name);    }    @Override    public String findLibrary(String name) {        return pathList.findLibrary(name);    }    @Override    protected synchronized Package getPackage(String name) {        if (name != null && !name.isEmpty()) {            Package pack = super.getPackage(name);            if (pack == null) {                pack = definePackage(name, "Unknown", "0.0", "Unknown",                        "Unknown", "0.0", "Unknown", null);            }            return pack;        }        return null;    }    /**     * @hide     */    public String getLdLibraryPath() {        StringBuilder result = new StringBuilder();        for (File directory : pathList.getNativeLibraryDirectories()) {            if (result.length() > 0) {                result.append(':');            }            result.append(directory);        }        return result.toString();    }    @Override public String toString() {        return getClass().getName() + "[" + pathList + "]";    }}final class DexPathList {    private static final String DEX_SUFFIX = ".dex";    private static final String zipSeparator = "!/";    ...        public Class findClass(String name, List<Throwable> suppressed) {        for (Element element : dexElements) {            DexFile dex = element.dexFile;            if (dex != null) {                Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);                if (clazz != null) {                    return clazz;                }            }        }        if (dexElementsSuppressedExceptions != null) {            suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));        }        return null;    ...    }}

Android 中的动态加载难点

  • 有许多组件类需要注册后才能使用
  • 资源的动态加载很复杂
  • Android 程序运行需要一个上下文环境