在Replugin 这个框架中,360实现了只需要hook一个点,就可实现插件化加载,而这个点就是classloader。为什么hook这个点就能解决Activity 动态加载的问题,这个就要从我们的Activity是怎么来的说起了,Activity的启动代码相当复杂,在这里就不分析了,网上有不少大神的blog都分析了这个问题,其中跟hook点最相关的就是下面的这一段。
这一段从ActivityThread的 performLaunchActivity 方法中摘出,
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
进入mInstrumentation 的 newActivity 方法:
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
看到这个方法是不是就有一种恍然大悟的感觉了,最终的Activity 实例是通过其 Activity 的class对象调用newInstance()得到的. 所以只需要控制了 Activity的class 对象, 就控制了Activity的产生,而这个class对象,正是我们可以通过hooK来解决的。
在这里Relugin 框架解决了Activity 怎么来的问题,同时因为Activity需要在AndroidManifest中注册,所以在使用Replugin 框架的时候,框架的插件会在生成的Apk文件中添加很多的Activity组件来作为一个个占坑,比如当我们启动的一个Activity A 的时候,Relugin 会将我们的目标Activity替换为坑位中的一个Activity AP ,但是在实际返回这个Activity目标class 对象的时候,返回的却是Activity A 的class 对象。
走完这个流程,Replugin 的核心原理应该就算是掌握了,虽然说得这么简单,但是其中每个步骤都相当的复杂,继续学习吧。
具体实现可以看下demo