动态加载

Java J类中加载so库并声明native方法,javac com/t/j.java编译并javah com/t/j导出com_t_j.h 的jni头文件在当前目录下,在工程主目录下创建文件夹,放入刚才的头文件并创建新文件(hkkk.c/cpp)实现相关方法,并编译出.so。

配置NDK,Java J类中加载so库并声明native方法,外部创建jni目录创建文件c/cpp文件们,android{defaultConfig{jndk{moduleName "so-name"}} productFlavors{arm{ndk{abiFilter "armeabi"}} //x86{ndk{abiFilter "x86"}取所需,默认自动编译所有平台()}}}, Andorid.mk(LOCAL_PAT :=$(call my-dir)   include $(CLEAR_VARS)  LOCAL_MODULE :=so-name//模块名  LOCAL_SRC_FILES :=j.c//要编译的源文件 include $(BUILD_SHARED_LIBRARY)), Application.mk(APP_ABI :=armeabi//所需支持的平台), 默认编译jni下的源文件,android{sourceSets.main{jni.srcDirs 'src/main/jnilj'}}可改编译源

AS .so默认加载目录为jniLibs(可直接System.loadLibrary),也可在android{sourceSets.main{jniLibs.srcDir 'src/main/some'}}设置成其它的


安装apk的时候,解析apk,解压然后读取libs目录下的so文件,获取应用所支持的arch架构类型,本地释放解压到指定目录。64位(5.0系统后,通过ro.product.cpu.abilist属性值来判断,若含64即64位系统;5.0之前都是32位,可通过ro.product.cpu.abi值判断)系统会启动两个Zygote进程兼容32位应用(so)。启动应用时AMS.startProcessLocked()向Zygote进程发送一个消息,为应用创建相应虚拟机.再拼接so文件的全路径加载(DexClassLoader的nativeLib路径;System.load加载全局路径的so文件;System.loadLibrary)之。

Could not find libxxx.so:so文件的释放是系统会先遍历apk中所有so文件的全路径,然后在结合abiList的值来决定最终释放哪个目录中的so文件,若系统是arm64-v8a,而apk中的libs下也有arm64-v8a,就会把apk中的libs\arm64-v8a中的所有so文件释放解压到本地目录中,而不会在去释放armeabi/armeabi-v7a。所以使用so文件的时候,需要确定在每个架构类型目录中都要有相同的so文件(arm架构向下兼容)。
32-bit instead of 64-bit:64位的Zygote进程创建的虚拟机中加载了32位的so文件:一是我们把不同架构类型的so文件放错目录了,比如armeabi/armeabi-v7a的so文件放到了arm64-v8a中了;二是比如宿主工程中有arm64-v8a目录,系统的abiList中也有arm64-v8a类型,所以这时候应用的ApplicationInfo的abi就是arm64-v8a,但是插件中加载so却是armeabi/armeabi-v7a类型的。    类似:64-bit instead of 32-bit:32位的虚拟机中加载了64位的so文件问题导致
Shared library already opened:用不同的DexClassLoader实例多次加载了相同的so文件:用一DexClassLoader加载过so后,进程没被kill时so没有释放还在内存中,一个新的(比如用DexClassLoader类去加载插件,为了插件能够实时更新)DexClassLoader对象再去加载so。解决:如调用System.exit(0)杀进程;单例DexClassLoader。


//updating 

HTML  apk(编译/打包),dex

DexClassLoader(path、dexOutDir:保存解压出的dex文件、libPath:加载的时候需要用到的lib库,一般不用,一般包括/vendor/lib和/system/lib、parent:给DexClassLoader指定父加载器)可以加载任何路径apk/dex/jar;
PathClassLoader(默认path, libPath, parent:BootClassLoader)加载/data/app, /system/app/中的apk,,是已经安装到手机中的apk,解压释放dex到/data/dalvik-cache,然后在优化成odex


资源文件访问:A生命周期管理:class ProxyA{

AssetManager  mAssetManager ;       Resources  mResources ;  private DexClassLoader classLoader;

@override public AssetManager getAssets(){

return mAssetManager ==null? super.getAssets() : mAssetManager;

}

@override public Resources getResources (){

return mResources == null? super.getResources (): mResources ;

}

protected void loadResources(){

try{

AssetManager assetManager = AssetManager.class.newInstance();  
                Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);  
                addAssetPath.invoke(assetManager, dexpath);  
                mAssetManager = assetManager;  

}catch(Exception e){e.printStackTrace();}

Resources superRes = super.getResources();  
            superRes.getDisplayMetrics();  
            superRes.getConfiguration();  
            mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),superRes.getConfiguration());  

}

}

ClassLoader管理:




热更新:在运行时反射更改PathClassLoader.pathList.dexElements,构造自己的dex文件。所对应的dexElements数组的时候,就是通过构造一个DexClassLoader对象来加载dex文件,并且调用一次dexClassLoader.loadClass(dummyClassName); 
dexClassLoader.pathList.dexElements中,就会包含我们的dex,通过把dexClassLoader.pathList.dexElements插入到系统默认的classLoader.pathList.dexElements列表前面,就可以让系统优先加载我们的dex中的类




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值