热修复原理学习(7)so库加载原理,android开发网

static void unregisterJNINativeMethods(Method* methods, size_t count) {

while(count != 0) {

count–;

Method* meth = &methods[count];

if (!dvmIsNativeMethod(meth)) {

continue;

}

if (dvmIsAbstractMethod(meth)) { /* avoid abstract method stubs */

continue;

}

dvmSetNativeFunc(meth, dvmResolveNativeMethod, NULL); // meth->nativeFunc重新指向dvmResolveNativeMethod

}

}

UnregisterNatives函数会把jclazz所在类的所有native方法都重新指向为dvmResolveNativeMethod,所以调用UnregisterNatives 之后不管是静态注册还是动态注册native方法、之前是否执行过,在加载补丁so的时候都会重新去做映射。

所以我们只需要调用:

static void patchNativeMethod(JNIEnv *env, jclass clz) {

env->UnregisterNatives(clz);

}

这里有一个难点,因为native方法是在so库,所以补丁工具很难检测出到底是哪个Java类需要解除native方法的注册。 这个问题暂且放下。

假设我们现在可以知道哪个具体的Java类需要解除注册native方法,然后load补丁库,再次执行该native方法,按照道理来说是可以让native方法实时生效,但是测试发现,在补丁so库重命名的前提下,Java层native方法可能映射到原so库的方法,也可能映射到补丁so库的修复后的新方法。(即时而生效,时而不生效)

首先,静态注册的native方法之前从未执行过的话或者调用了UnregisterJNINativeMethods方法解除注册,那么该方法将指向dvmResolveNativeMethod(meth->nativeFunc = dvmesolveNativeMethod),那么真正运行该方法的时候,实际上执行的是dvmResolveNative()方法。这个函数主要完成Java层的native方法和native层方法的逻辑映射。

void dvmResolveNativeMethod(const u4* args, JValue* pResult, const Method* method, Thread* self) {

void* func = lookupSharedLibMethod(method);

… …

if (func != NULL) {

// 调用lookupSharedLibMethod方法,拿到so库文件对应的native方法函数指针。

dvmUseJNIBridage((Method*) method,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值