美文网首页面试题
Android类加载(二)——双亲委托机制

Android类加载(二)——双亲委托机制

作者: 程序员三千_ | 来源:发表于2020-03-16 13:25 被阅读0次

Android类加载(一)——DVM、ART、Dexopt、DexAot名词解析
Android类加载(二)——双亲委托机制
Android类加载(三)——源码解读

Java类加载器

定义
  • BootClassLoader
    用于加载Android FrameWork层的class文件(系统的Activity)
  • PathClassLoader
    用于加载Android应用程序的class 文件(自己写的MainActivity)
    也可以加载指定的dex,以及jar、zip、apk中的classes.dex
  • DexClassLoader
    加载指定的dex,以及jar、zip、apk中的classes.dex

比较PathClassLoader和DexClassLoader

  • 在一个app安装的过程中,Android系统是没有用到DexClassLoader类的,而PathClassLoader会被用于加载Android应用程序的class 文件(例如自己写的MainActivity),DexClassLoader类就是提供给开发者使用的类,Android FrameWork层并没有使用到DexClassLoader。
  • 构造方法的区别
public class DexClassLoader extends BaseDexClassLoader {
    /**
     * Creates a {@code DexClassLoader} that finds interpreted and native
     * code.  Interpreted classes are found in a set of DEX files contained
     * in Jar or APK files.
     *
     * <p>The path lists are separated using the character specified by the
     * {@code path.separator} system property, which defaults to {@code :}.
     *
     * @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; must not 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 DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}
public class PathClassLoader extends BaseDexClassLoader {
    /**
     * Creates a {@code PathClassLoader} that operates on a given list of files
     * and directories. This method is equivalent to calling
     * {@link #PathClassLoader(String, String, ClassLoader)} with a
     * {@code null} value for the second argument (see description there).
     *
     * @param dexPath the list of jar/apk files containing classes and
     * resources, delimited by {@code File.pathSeparator}, which
     * defaults to {@code ":"} on Android
     * @param parent the parent class loader
     */
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    /**
     * Creates a {@code PathClassLoader} that operates on two given
     * lists of files and directories. The entries of the first list
     * should be one of the following:
     *
     * <ul>
     * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
     * well as arbitrary resources.
     * <li>Raw ".dex" files (not inside a zip file).
     * </ul>
     *
     * The entries of the second list should be directories containing
     * native library files.
     *
     * @param dexPath the list of jar/apk files containing classes and
     * resources, delimited by {@code File.pathSeparator}, which
     * defaults to {@code ":"} on Android
     * @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 PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}

从源码里可以看出它们都派生于BaseDexClassLoader类,但在它们的构造方法稍有不同

public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
public PathClassLoader(String dexPath, String libraryPath,
           ClassLoader parent) {
       super(dexPath, null, libraryPath, parent);
   }

有三个参数是一样的

  • dexPath:要加载的dex所在的目录
  • libraryPath:Native方法so文件所在的目录
  • parent:可以理解为双亲加载机制里的所谓的“父亲”(双亲委托机制下面再讲)
  • optimizedDirectory:opt优化后的dex文件所在的目录(而且从源码的注释里可以看到,这个目录必须为私有目录,不能为sd卡的目录)

而DexClassLoader就比PathClassLoader多了一个optimizedDirectory参数,
也就是说DexClassLoader用于存储opt优化后的dex文件的保存路径可以自己定义传进去,而PathClassLoader存储opt优化后的dex文件的保存路径是系统默认的。仅此这个区别而已。

双亲委托机制

类加载在加载类时,首先将加载任务委托给父类加载器加载,依次递归,如果父类加载器可以完成加载任务,就成功返回,如果父类加载器无法完成或者没有父类加载器时,才自己去加载。
简单一个词语概括:啃老族机制。

下面我们用一段代码来进行解释:


public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //PathClassLoader
        ClassLoader classLoader = this.getClassLoader();
        //BootClassLoader
        ClassLoader classLoader1 = Activity.class.getClassLoader();
        
        System.out.println("PathClassLoader getClassLoader:"+classLoader);
        System.out.println("PathClassLoader getClassLoader 的父亲 :"+classLoader.getParent());
        System.out.println("BootClassLoader Activity.class :"+classLoader1);

image.png

从打印中我们可以得出以下结论

  • MainActivity的类加载器是PathClassLoader
  • Activity的类加载器是PathClassLoader
  • PathClassLoader的父亲是BootClassLoader

注意:这里所说的父亲并不是指这个类的父类(BaseDexClassLoader),只是ClassLoder类里的一个类型为ClassLoader的成员变量名称叫做parent

image.png image.png
那么为什么要使用双亲委托机制呢?

在我们应用程序启动的时候,BootClassLader会去加载FrameWork层的所有的类,例如上面的Activity,而我们自己写的代码BootClassLader是没办法去加载的,只能由PathClassLoader去加载,因为我们自己写的代码的类,在我们的apk里面,不在系统里面,例如上面的MainActivity。但现在我们写的MainActivity是派生于AppCompatActivity的,AppCompatActivity属于FrameWork层的类,已经被BootClassLader加载了,如果我们不使用双亲委托机制的话,PathClassLoader是不是加载不到FrameWork层的类,那是不是加载不了AppCompatActivity了,而运用双亲委托机制就能很好的让不同的类加载器去分别执行不同层级的类加载的任务,这样也是有利于系统的安全性,对于开发者来说你是无法知道怎么去加载系统的类的,你永远只能加载自己写的类,系统层面的类是不让你去加载的,只能由父亲BootClassLader去加载。

相关文章

  • Android的类加载器

    Android的ClassLoader与java的ClassLoader有些差异, 双亲委托机制某个类加载器在加载...

  • 【JAVA】京东一面

    1、类加载机制概念、加载步骤、双亲委托机制、全盘委托机制、类加载器种类及继承关系 2、如何实现让类加载器去加载网络...

  • 3.类加载器三双亲委托机制

    双亲委托机制 在双亲委托机制中,各个加载器按照父子关系形成了树形结构,除了根类加载器之外,其余的类加载器都有且只有...

  • Android类加载(二)——双亲委托机制

    Android类加载(一)——DVM、ART、Dexopt、DexAot名词解析Android类加载(二)——双亲...

  • 四、初识ClassLoader

    双亲委派的定义 类加载器的父亲委托机制(双亲委派机制) 类加载器加载一个类时,会优先交给其父的加载器加载,父加载器...

  • JVM之双亲委托机制

    JVM之双亲委托机制 前言: 想了解双亲委托机制,我们就得先了解他的ClassLoader(类加载)。不管是And...

  • jvm(二)类加载过程与类加载器

    本篇内容: 类加载过程 类加载器分类 双亲委托机制 沙箱安全机制 类加载过程 类加载器子系统负责将从文件系统或者网...

  • 【Java基础】类加载过程

    要点:1、类加载机制的原理2、程序初始化的顺序3、类加载的代理模式(双亲委托机制) 一、类加载机制 JVM把cla...

  • ClassLoader

    双亲委托机制 自己先加载,加载到返回class,加载不到让父类加载,如此往复,最后还是加载不到,抛出异常。 好处 ...

  • java类加载机制

    类加载机制-双亲委托机制 例如:当jvm要加载Test.class的时候, (1)首先会到自定义加载器中查找,看是...

网友评论

    本文标题:Android类加载(二)——双亲委托机制

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