Androidso的热升级尝试-创新互联

一、So的热升级尝试

创新互联建站主营临川网站建设的网络公司,主营网站建设方案,手机APP定制开发,临川h5小程序开发搭建,临川网站营销推广欢迎临川等地区企业咨询

在Android代码中,加载so库是通过调用System.loadLibrary函数实现的。但和Android的许多特性一样,只提供了加载,而没有卸载和更换等功能。为了研究能否实现卸载和升级等功能,首先要了解清楚JNI so加载的流程。

在以上流程中,使用dlopen加载so之后,会继续调用JNI_Onload函数,通过系统提供的RegisterNatives函数完成一些列初始化,向虚拟机注册so库提供的JNI函数。So库也可以不实现JNI_Onload函数,而是采用自动查找的方式。

Android虚拟机会在首次调用JNI函数时按照JNI规范的命名规则自动查找。通过分析Android代码,这种方法最终也会调用到上图中的dvmSetNativeFunc等函数,将函数地址保存到虚拟机中供下次调用。

二、卸载及重新加载

如果想要提供热升级的能力,首先要做的是关闭已打开的so文件。但Android虚拟机没有提供unloadLibrary这样的接口,因此需要我们自己自己实现。

根据上一节的分析,loadLibrary在native层加载文件使用的是dlopen,与之对应的系统接口是dlclose。而接下来的RegisterNatives由于没有对应的unRegister,我们暂且先放一放,看看卸载的效果再来处理。

卸载so

提供卸载能力的接口需要完成以下几项任务:

1、找到要卸载so的句柄;

2、调用JNI_OnUnload;

3、调用dlclose卸载。

如下便是我们写出的卸载函数:

void JNICALL Java_com_example_Unloader_unload(JNIEnv* env, jobject obj)
{
void* handle = dlopen(“/data/data/com.example.unloader/lib/libtest.so”, RTLD_GLOBAL);
if(!handle) return;
LOGD(“unload so: 0x%x\n”, (unsigned int)handle);
void* symbol = dlsym(handle, “JNI_OnUnload”);
if(symbol)
{
OnLoadFunc func = (OnLoadFunc)symbol;
JavaVM* jvm = 0;
(*env)->GetJavaVM(env, &jvm);
if(jvm)
(*func)(jvm, 0);
}
int result = dlclose(handle);
LOGD(“unload result %d\n”, result);
result = dlclose(handle);
result = dlclose(handle);
LOGD(“unload result %d\n”, result);
}

本文题目:Androidso的热升级尝试-创新互联
本文来源:http://scyanting.com/article/hodos.html