使用DexClassLoader类动态加载插件dex

DexClassLoader类的源码

package dalvik.system;

public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String librarySearchPath, ClassLoader parent) {
        super(dexPath, null, librarySearchPath, parent);
    }
}

DexClassLoader类构造方法参数:

  • String dexPath:指定了 .dex 文件的路径。
  • String optimizedDirectory:指定了优化后的 .dex 文件存放的目录。在 Android 系统中,为了提高应用的启动速度和运行效率,会对 .dex 文件进行优化,生成 .odex 文件。这个参数就是用来指定优化后的 .odex 文件存放的位置。
  • String librarySearchPath:指定了系统库文件的搜索路径。
  • ClassLoader parent:指定了父类加载器。

编写插件加载dex中的类,并调用其中的函数

PluginDex01

新建一个native工程PluginDex01
创建一个类

public class PluginClass {
    public static void testMethod(){
        Log.e("plugindex","testMethod is called");
    }
}

然后编译生成apk(Build apk),然后提取apk
在这里插入图片描述
这里生成了四个dex文件,查看他们的内容找到有testMethod函数的dex文件
通过jadx反编译dex找到在class3.dex
在这里插入图片描述
class3.dex改名为plugin.dex,然后通过adb把它push到/data/local/tmp目录下

在这里插入图片描述

PluginDex02

新建一个工程PluginDex02,用来加载dex中的PluginClass类并调用testMethod函数
首先需要在AndroidManifest.xml中添加sdcard读取权限
在这里插入图片描述
编写代码加载plugin.dex并调用testMethod函数

        String dexpath = "/data/local/tmp/plugin.dex";  // dex路径
        DexClassLoader dexClassLoader = new DexClassLoader(dexpath,this.getApplication().getCacheDir().getAbsolutePath(),null,MainActivity.class.getClassLoader());
        try {
            Class PluginClass = dexClassLoader.loadClass("com.example.plugindex01.PluginClass"); // 加载类
            Log.e("PluginDex02",dexClassLoader.toString()+"---"+PluginClass.toString());
            Method testMethod = PluginClass.getMethod("testMethod");
            testMethod.invoke(null);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

在这里插入图片描述

  • 打印dexClassLoader的父类加载器
    printClassLoader(dexClassLoader);
    在这里插入图片描述

    this->dalvik.system.DexClassLoader[DexPathList[[dex file "/data/local/tmp/plugin.dex"],nativeLibraryDirectories=[/system/lib64]]]
    parent->dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/lib/arm64, /data/app/com.example.plugindex02-GQcsk_5ktyHhY_g_qUMA-A==/base.apk!/lib/arm64-v8a, /system/lib64]]]
    parent->java.lang.BootClassLoader@84d413c
    parent is null
    

    dexClassLoader的类加载器是DexClassLoader,父类加载器是PathClassLoader,再往上是BootClassLoader,再往上就是空了

  • 把dexClassLoader里的父类加载器修改为String类的类加载器
    只需要在DexClassLoader类的构造方法里把最后一个参数父类加载器修改为String类的类加载器即可

            String dexpath = "/data/local/tmp/plugin.dex";  // dex路径
            DexClassLoader dexClassLoader = new DexClassLoader(dexpath,this.getApplication().getCacheDir().getAbsolutePath(),null,String.class.getClassLoader());
    

    打印结果
    在这里插入图片描述
    dexClassLoader的父类加载器变成了BootClassLoader

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值