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 方法。