类的加载(doing)
2018-12-12 本文已影响0人
Wi1ls努力努力再努力
双亲委派模型
loadClass(String,boolean)@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;
}
-⑴查找本加载器是否已经加载过这个 class
- 若没有
-⑵优先请求父类加载- 若父类未加载过且加载失败
- ⑶本加载器进行加载
- 若父类未加载过且加载失败
ClassLoader.java
protected ClassLoader(){
this(getSystemClassLoader(), false);
}
protected ClassLoader(ClassLoader parentLoader){
this(parentLoader, false);
}
ClassLoader(ClassLoader parentLoader, boolean nullAllowed){
if(parentLoader == null && !nullAllowed){
threow new NullPointerException("parentLoader == null && !nullAllowed);
}
parent = parentLoader;
}
pubic static ClassLoader getSystemClassLoader(){
return SystemClassLoader.loader;
}
static private class SystemClassLoader{
public static ClassLoader loader = ClassLoader.createSystemClassLoader();
}
private static ClassLoader createSystemClassLoader(){
String classPath = System.getProperty("java.class.path",".");
return new PathClassLoader(classPath,BootClassLoader.getInstance());
}
- 当 CustomClassLoader 时,不指明其 parentLoader,默认parent 为 PathClassLoader,同时 PathClassLoader 的 parentLoader 是 BootClassLoader。同事也可以看出,PathClassLoader 加载System.getProperty("java.class.path",".")下的 dex 相关;
PathClassLoader 和 DexClassLoader 继承自 BaseDexClassLoader,其主要逻辑都在 BaseDexClassLoader,不同点在于构造函数传入的参数。
DexClassLoader
public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent){
super(dexPath, new File(optimizedDirectory), libraryPath, parent);
}
PathClassLoader
public PathClassLoader(String dexPath, ClassLoader parent){
super(dexPath, null, null, parent);
}
public PathClassLoader(String dexPath, String libraryPath, ClassLoader parent){
super(dexPath, null, library, parent);
}
BaseDexClassLoader
/**
* Constructs an instance.
*
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android
* @param optimizedDirectory directory where optimized dex files
* should be written; may be {@code null}
* @param libraryPath the list of directories containing native
* libraries, delimited by {@code File.pathSeparator}; may be
* {@code null}
* @param parent the parent class loader
*/
public BaseDexClassLoader(String dexPath, File optimizedDirectory, String libraryPath, ClassLoader parent){
super(parent);
this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
}
- 参数介绍
- dexPath:dex 相关文件路径集合,多路径用文件分隔符分割,默认“:”
- optimizedDirectory:解压的 dex 文件存储路径,必须是内部存储路径。一般情况下使用/data/data/<Package Name>/...
- librarySerchPath:包含 c/c++库路径,多路径分割,可为 null
- parent:父加载器
findClass(String)@BaseDexClassLoader.java
protected Class<?> findClass(String name) throws ClassNotFoundException{
List<Throwable> suppressedExceptions = new ArrayList<Throwable>( );
Class c = pathList.findClass(name, suppressedExceptions);
return c;
}
上述的 pathList 在构造函数中实例化,是 DexPathList 对象
DexPathList
public DexPathList(ClassLoader definingContext, String dexPath, String libraryPath, File optimizedDirectory){
...
this.definingContext = definingContext;
this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory, suppressedExceptions);
this.nativeLibraryDirectories = splitPaths(libraryPath, false);
this.systemNativeLibraryDirectories = splitPaths(System.getProperty("java.library.path"), true);
this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null, suppressedExctprions);
}
public Class findClass(String name, List<Throwable> suppressed){
for(Element element : dexElements){
DexFile dex = element.dexFile;
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
return clazz;
}
}
DexFile.java
public Class loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed){
return defineClass(name, loader, mCookie, suppressed);
}
private static Class defineClass(String name, ClassLoader loader, Object cookie, List<Throwable> suppressed){
Class result = defineClassNamtive(name, loader, cookie);
}