Foo.bar()这种直接调用与反射调用Foo.class.getDeclaredMethod(“bar”).invoke(null) 有什么区别吗?这个问题后续再谈
private native Object invoke(Object receiver, Object[] args, boolean accessible)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
这个invoke是一个native方法,它的native实现在 art/runtime/native/java_lang_reflect_Method.cc 里面,这个jni方法最终调用了 art/runtime/reflection.cc 的 InvokeMethod方法:
object InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
jobject javaReceiver, jobject javaArgs, bool accessible) {
// 略...
mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
mirror::Class* declaring_class = m->GetDeclaringClass();
}
AndFix的实现里面,也正是使用这个 FromReflectedMethod 方法拿到Java层Method对应native层的ArtMethod指针,然后执行替换的
首先简单介绍下ART上的方法调用原理(本文不讨论解释模式,所有entrypoint均指compiled_code_entry_point)。在ART中,每一个Java方法在虚拟机(注:ART与虚拟机虽有细微差别,但本文不作区分,两者含义相同,下同)内部都由一个ArtMethod对象表示(native层,实际上是一个C++对象),这个native 的 ArtMethod对象包含了此Java方法的所有信息,比如名字,参数类型,方法本身代码的入口地址(entrypoint)等;暂时放下trampoline以及interpreter和jit不谈,一个Java方法的执行非常简单:
AndFix就是基于这个原理来做热修复的,Sophix 对这个方案做了一些改进,也即整体替换,不过原理上都一样。二者在替换方法之后把原方法直接丢弃,因此无法实现AOP
《深入探索Android热修复技术原理》–Sophix团队
两种情况不适用: