Android基础——类加载器和动态加载

类加载器和动态加载

一、类加载器:

双亲委派模式

·(以递归的形式逐级向上)(一般java有三层类加载器)
·三层:
1)系统类加载器(应用程序类加载器):AppClassLoader
ClassLoader.getSystemClassLoader()
2)系统类加载器的父类加载器(扩展类加载器):Extension ClassLoader
ClassLoader.getSystemClassLoader.getParent()
3)扩展类加载器的父类加载器(启动类加载器)(C++编写):Bootstrap ClassLoader
在这里插入图片描述
·双亲委派模式:在加载.class文件时,以递归的形式逐级向上委托给父加载器,如果加载过就不用再加载一次了,直接返回,如果未加载过,继续向上委托给父加载器,直到链路顶级,如果顶级加载器未加载过,则尝试加载,加载失败(在他的搜索范围中没有找到所需的类)则逐级向下交还给子加载器调用自己的findClass()方法进行加载。

·findClass和defineClass
用来将byte字节解析成虚拟机能够识别的Class对象。defineClass()方法通常与findClass()方法一起使用。在自定义类加载器时,会直接覆盖ClassLoader的findClass()方法获取要加载类的字节码,然后调用defineClass()方法生成Class对象。

二、Android中类加载机制

·类加载机制:.java不可执行,需要先编译成.class文件
·虚拟机:java虚拟机运行JVM,运行的是.class文件;Android虚拟机是dalvik/art,运行的是dex文件(class文件的集合)
·Android运行流程
1)Android程序编译的时候,会将.java文件编译成.class文件
2)生成apk时,将.class文件打包为.dex文件(不是简单的压缩,而是完全对class文件内部的各种函数表、变量表等进行优化,所以java和Android中的classloader也不一样)
3)Android程序运行时,虚拟机加载dex文件,然后加载其中的.class文件到内存中来使用
·类加载流程:类被加载到虚拟机内存:加载(插件化可以实现)、连接(验证、准备、解析)、初始化(执行实际程序中的代码)
·类加载时机
1)显式加载:使用LoadClass()、forName()加载
2)隐式加载:创建类的实例(new一个对象)、初始化类的子类(先初始化子类的父类)、访问某个类或接口的静态变量或对该静态变量赋值、调用类的静态方法、反射Class.forName(“android.app.ActivityThread”)
·Android类加载器
在这里插入图片描述
·findLoadedClass[–>ClassLoader.java]
源码链接

    protected final Class<?> findLoadedClass(String name) {
   
        ClassLoader loader;
        if (this == BootClassLoader.getInstance())
            loader = null;
        else
            loader = this;
        return VMClassLoader.findLoadedClass(loader, name);
    }

·findClass[–>BaseDexClassLoader.java]
源码链接

    protected Class<?> findClass(String name) throws ClassNotFoundException {
   
        // First, check whether the class is present in our shared libraries.
        if (sharedLibraryLoaders != null) {
   
            for (ClassLoader loader : sharedLibraryLoaders) {
   
                try {
   
                    return loader.loadClass(name);
                } catch (ClassNotFoundException ignored) {
   
                }
            }
        }
        // Check whether the class in question is present in the dexPath that
        // this classloader operates on.
        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
        Class c = pathList.findClass(name, suppressedExceptions);
        if (c != null) {
   
            return c;
        }
        // Now, check whether the class is present in the "after" shared libraries.
        if (sharedLibraryLoadersAfter != null) {
   
            for (ClassLoader loader : sharedLibraryLoadersAfter) {
   
                try {
   
                    return loader.loadClass(name);
                } catch (ClassNotFoundException ignored) {
   
                }
            }
        }
        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;
    }

·DexPathList.findClass:

·Android中的ClassLoader

1.BootClassLoader

·启动类加载器(最顶级的那个),加载Zygote进程已经预加载(Class.forName())的基本类,只需从缓存中加载;内部类,应用程序无权直接访问
(基本类:object、class、classloader、string等)
·没有父类加载器,调用自己的findClass()方法—>调用Class.classForName()方法
·预加载:ZygoteInit.preloadClasses()中调用Class.forName(),实际是指定BootClassLoader为类加载器,且只需要在预加载的时候进行类初始化,只需要一次。
·Class.classForName()方法和Class.forName()方法仅可以直接加载基本类,且两种方法都是动态加载class文件。
在这里插入图片描述
·无论是系统类加载器(PathClassLoader)还是自定义的类加载器(DexClassLoader),最顶层的根类加载器默认是 BootClassLoader

2.PathClassLoader

·可以加载系统类和应用程序的类,通常用来加载已安装的apk的dex文件
·在Zygote进程启动的时候初始化,在预加载基本类之后执行(在APP进程中),所以每个APP进程从Zygote进程中fork出来之后都自动携带一个PathClassLoader。
·创建PathClassLoader的过程就是加载dex文件的过程

3.DexClassLoader

·可以加载dex文件以及包含dex文件的压缩文件(比如apk、jar、zip等),也就是从包含classes.dex的文件中加载类,能够加载系统未安装的apk或者jar文件,一般为自定义类加载器
·可以实现动态加载,因为它提供了optimizedDirectory,它是用来存放dex文件的地方。

<
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值