Dalvik虚拟机反射调用函数执行流程

Dalvik虚拟机函数执行有以下几种方式:

  1. interpreted 调用 interpreted
  2. interpreted 调用 native
  3. native 调用 interpreted
  4. native 调用 native
  5. 反射调用 interpreted
  6. 反射调用 native

本章主要分析反射调用。新建一个工程如下:

 public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Method method = MethodUtils.getMatchingAccessibleMethod(MainActivity.class, "test", String.class);

        try {
            String result = (String) method.invoke(MainActivity.class, "hello");
            Toast.makeText(this, result, Toast.LENGTH_LONG).show();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static String test(String name) {
        return "invoked: " + name;
    }
}

这个Method的invoke是调到哪里了?

public Object invoke(Object receiver, Object... args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (args == null) {
            args = EmptyArray.OBJECT;
        }
        return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
    }

private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass,
        Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
                throws IllegalAccessException, IllegalArgumentException,
                        InvocationTargetException;

可见是调到invokeNative了,这是个native函数,具体实现如下:

static void Dalvik_java_lang_reflect_Method_invokeNative(const u4* args, JValue* pResult)
{
    meth = dvmSlotToMethod(declaringClass, slot);

    ..................

    result = dvmInvokeMethod(methObj, meth, argList, params, returnType, noAccessCheck);

    RETURN_PTR(result);
}

可见这里是调用了dvmInvokeMethod来执行反射的函数的。我们再来看dvmInvokeMethod的实现:

Object* dvmInvokeMethod(Object* obj, const Method* method,
    ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
    bool noAccessCheck)
{
    clazz = callPrep(self, method, obj, !noAccessCheck);

    ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
    verifyCount = 0;

    if (!dvmIsStaticMethod(method)) {
        *ins++ = (s4) obj;
    }

    if (dvmIsNativeMethod(method)) {
        (*method->nativeFunc)(self->curFrame, &retval, method, self);
    } else {
        dvmInterpret(self, method, &retval);
    }

    dvmPopFrame(self);

    return retObj;
}

可见这里的实现和dvmCallMethodV非常类似,就不再赘述了。具体可参考我的这篇文章:
Xposed研究——Dalvik虚拟机线程初始化及函数执行流程

总结一下,通过反射调用一个函数,首先要获取Dalvik虚拟机中该函数的Method对象,然后要为这个函数开辟一块栈帧,如果该函数不是native的,则将pc指向该函数的指令码数组,然后在循环中依次取指令执行,直到函数返回,再恢复栈帧和pc。如果该函数是native的,则直接跳转到该nativeFunc执行,完后恢复栈帧即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值