Android 类加载机制、反射 和 动态代理

860 阅读3分钟

1   类记载机制      

JVM 类加载 器 从顶向下 主要有 BootStrapClassLoader,  ExtClassLoader   AppClassLoader  这些在Android 源码 里面 找不到具体的定义 应该数据 jdk 的包里面 

      BootStrapClassLoader 加载核心类,由C++ 来实现,核心类 比如String。  ExtClassLoader AppClassLoader  位于 security 包下面,是跟安全相关的,

       类加载使用双亲委派模式,就是先 使用双亲 的加载器进行加载,如果双亲没有加载完成,再用自己的加载器进行加载,避免了自己定义的假的java 类,替代掉了jdk 定义的类,会产生不安全的隐患。保证类的唯一性。向上传递 和向下查找的过程。防止内存中出现多份同样的字节码。

     Android 类加载机制 主要有三个类:属于 dalvik.system  包下面  PathClassLoader(DelegateLastClassLoader)   DexClassLoader 和 InMemoryClassLoader  都是继承 BaseClassLoader, 就是把一个文件加载到内存中的对应的类

       从源码的注释看三个类的作用:

      PathClassLoader  加载应用内部的文件,不会加载外部的文件。Android 使用它进行应用内部文件的加载 

    DexClassLoader  可以加载外部dex  jar  apk  文件,加载不是已经安装的系统的文件。建议文件放在 context.getCodeCacheDir 里面。   

    InMemoryDexClassLoader  加载内存里面的 dexFile ,可以执行 还没有写进本地文件系统的代码

     类加载 就是  把 .class  文件或者 dex 文件 的类  实例化一个对象出来,系统外部根据类名获取二进制流,交给jvm ,然后实例化成class 实例,ClassLoader 只作用于类加载。  每个classLoader 构造函数 都会 传入 一个parent 的类,优先使用父类classLoader 来加载。 当父classLoader 无法加载的时候,才使用子自己的classLoader 进行加载 

     三个子类 实现 只有一个构造方法,调用父类的方法,最终调用到  BaseDexClassLoader 里面的findClass 里面的逻辑  :

Android 10: 

1、如果 sharelibaryLoader  ! = null ,使用 这个 classloader 进行架子啊

2 、 如果为空 执行 PathList.findClass (name); 

3 、PathList  负责  通过 方法 遍历dexElements  的集合, 里面 有 Elements 。

4、使用Element 里面 持有 DexFile 的引用。 通过DexFile  的 loadClassBinaryName 来记载类。defineClass --->defineClassNative () 来进行加载类。

 Android 9 : createClass ---- >modifyClass ----> defineClass ---- > classForName 几个方法来初始化类 ,  加载之后对类进行缓存,下次从Map 里面获取

2   反射

        反射是对类加载的高级用法,反射相关的类 位于 jdk中的  java.lang.reflect 包下面。 主要的类有 Constructor  Field  Method   Proxy   Type  InvocationHandler  这几个类 。在java.lang 的包下面 还有一个 class 类 

       初始化 一个类的方式: 通过 new 关键字,  通过Class 的方式 (newInstance ,constructure.newInstance ), 通过clone 的方法。  

      反射的应用场景 

     1、创建对象。代替 new的方式 的显示。

     2、 获取私有的构造方法 getDeclareConstructure   setAccessible(true)

     3 、获取私有的属性 getDeclaredField 

     4 、 获取私有方法   getDecalredMethod 

     5 、 反射系统的方法。   修改运行时变量的某些值

3   动态代理

       动态代理 和静态代理的区别是: 减少了代理类的定义 ,统一对代理方法进行流程的控制,前后控制 。

      动态代理的实现借助于 : Proxy  ClassLoader    InvocationHandler  Class ( 通过构造函数把真实的对象传过来)   几个类 和 newProxyInstance() 方法。实现原理是  通过  newProxyInstance 的方式来构建对象, 当对象调用自己的方法的时候, 会执行  InvocationHandler 中的  invoke 方法,调用 method.invoke (真实的对象) 方法来通过反射的方式执行方法。 在 执行invoke 前后都可以进行控制。

     看源码看 有点懵逼。 newProxyInstance 方法 后面 会调用 Constructure -->ConstructorAccessorImpl  --- > DelegatingConstructorAccess 

     由于接口不能通过new 的方式来创建对象,进而无法 获取方法的调用。 如果接口没有实现类,但是 想去调用接口里面的方法,并且封装自己的实现。 可以使用动态代理的方式。

     Retrofi 使用动态代理创建对象的方法。

     调用 Retrofit 的 create 方法。