类加载过程
-
我们写的
.java文件,通过javac编译生成.class字节码,JVM 能够识别并执行这些.class文件。Kotlin 也是如此,kotlinc会将.kt文件编译成.class,最终统一运行在 JVM 上。 -
在 Android 中,
.class文件会被打包进.dex。App 启动时,系统创建PathClassLoader,并将.dex的路径保存在其内部的DexPathList中——此时只是记录路径,类还未加载。 -
当执行到
new某个类时,ClassLoader才会遍历DexPathList,查找并加载该类。
“加载到内存” 的本质是:在 JVM 的方法区创建一个java.lang.Class对象,作为该类的“运行时模版”,后续通过new创建的实例都基于这个模版。
如果类已加载,ClassLoader会直接从缓存返回已有的Class对象,不会重复加载。 -
反射机制,就是我们可以通过一个实例(比如
user),调用getClass(),反向拿到它的Class模版。
就像:- 正常是“根据设计图建房子”(
new User()) - 反射是“通过房子反推设计图”,甚至可以修改设计图(如访问私有字段、调用私有方法),从而动态控制对象行为。
- 正常是“根据设计图建房子”(
-
双亲委派机制,是为了防止我们篡改系统类。
比如你写了一个java.lang.String,PathClassLoader想加载它,但必须先委托BootClassLoader。
而系统类早已被BootClassLoader加载并缓存,它会直接返回真正的String,你的恶意类根本无法加载——系统核心类因此得到保护。 -
实际的加载顺序是:
子加载器缓存 → 父加载器缓存 → 父加载器尝试加载 → 父加载失败 → 子加载器加载。
具体到 Android:
PathClassLoader先查自己缓存 → 委托BootClassLoader→BootClassLoader查自己缓存 → 尝试加载(失败)→ 回退到PathClassLoader自己加载。 - 热修复就是,修改设计图纸:通过反射机制,修改pathList,替换掉原来的class,这样要加载的时候,就会使用心得class

浙公网安备 33010602011771号