Android加壳与脱壳(一):类加载器与动态加载的关系与原理
深入理解类加载器和动态加载二者之间的关系和原理
类加载器
JVM的双亲委派
双亲委派模型
从 Java 虚拟机角度讲,只存在两种类加载器:
一种是启动类加载器(C++ 实现,是虚拟机的一部分);
另一种是其他所有类的加载器(Java 实现,独立于虚拟机外部且全继承自 java.lang.ClassLoader)
启动类加载器
加载 lib 下或被 -Xbootclasspath 路径下的类
扩展类加载器
加载 lib/ext 或者被 java.ext.dirs 系统变量所指定的路径下的类
引用程序类加载器
ClassLoader负责,加载用户路径上所指定的类库。
除顶层启动类加载器之外,其他都有自己的父类加载器。
工作过程:如果一个类加载器收到一个类加载的请求,它首先不会自己加载,而是把这个请求委派给父类加载器。只有父类无法完成时子类才会尝试加载。
具体代码实现:
1 | protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ |
作用
(1
) 防止同一个.class
文件重复加载
(2
) 对于任意一个类确保在虚拟机中的唯一性,由加载它的类加载器和这个类的全类名一同确立其在Java虚拟机中的唯一性
(3
) 保证.class
文件不被篡改,通过委派方式可以保证系统类的加载逻辑不被篡改
Android中类加载机制
进入JAVA层后,
Zygote总结:
(1
)解析init.zygote.rc中的参数,创建AppRuntime并调用AppRuntime.start()方法
(2
)调用AndroidRuntime的startVM()方法创建虚拟机,再调用startReg()注册JNI函数
(3
)通过JNI方式调用ZygoteInit.main(),第一次进入Java世界
(4
)registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求
(5
)preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高app启动效率
(6
)通过startSystemServer(),fork得力帮手system_server进程,也是Java Framework的运行载体(下面讲到system server再详细讲解)
(7
)调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作
Android的类加载机制和JVM一样遵循双亲委派模式,在dalvik/art启动时将所有Java基本类和Android系统框架的基本类加载进来,预加载的类记录在/frameworks/base/config/preloaded-classes
中
Android类加载器层级关系及分析
1 | Android中的ClassLoader类型分为系统ClassLoader和自定义ClassLoader。其中系统ClassLoader包括3种是BootClassLoader、DexClassLoader、PathClassLoader |
1 | 补充: |
无论是系统类加载器(PathClassLoader)还是自定义的类加载器(DexClassLoader),最顶层的祖先加载器默认是 BootClassLoader,与 JVM 一样,保证了基本类的类型安全
类加载时机:
1.
隐式加载:
(1
)创建类的实例,也就是new一个对象
(2
)访问某个类或接口的静态变量,或者对该静态变量赋值
(3
)调用类的静态方法
(4
)反射Class.forName("android.app.ActivityThread"
)
(5
)初始化一个类的子类(会首先初始化子类的父类)
2.
显示加载:
(1
)使用LoadClass()加载
(2
)使用forName()加载
中间是一些更底层的代码和分别做了什么事,我没看那么仔细,大概了解了一下,也就懒得整理
Android类加载详细流程:
实验
略
参考
Android加壳与脱壳(1)——深入理解类加载器和动态加载
[Dalvik虚拟机的启动过程分析](