美文网首页
类的加载(doing)

类的加载(doing)

作者: Wi1ls努力努力再努力 | 来源:发表于2018-12-12 11:58 被阅读0次

    双亲委派模型

    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);
    }
    

    相关文章

      网友评论

          本文标题:类的加载(doing)

          本文链接:https://www.haomeiwen.com/subject/cbeuhqtx.html