动态加载dex简析和实践

本文详细介绍了Android中动态加载dex的原理,通过反射获取DexClassLoader的dexElements,并与PathClassLoader合并,实现类的动态加载。同时,探讨了Apk动态加载的步骤,包括处理不同版本的DexPathList兼容性问题。此外,文章还讨论了Apk加壳和dex保护策略,如将classes.dex加密后动态加载,以提高应用的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android类加载器源码简析这篇博客可知:可以使用DexClassLoader动态加载含有dex的jar或apk文件,然后就可以使用loadClass()方法来加载Class;而应用(即App)是由PathClassLoader加载的。这两个类都继承了BaseDexClassLoader。它有一个私有的属性pathList,这个属性为DexPathList类型,记录加载的dex和so文件的信息。DexPathList中使用一个Element[]类型的dexElements属性记录加载的dex。如果我们先使用DexClassLoader加载jar或apk文件,然后通过反射获取到它的dexElememts。将其与PathClassLoader中dexElememts合并,然后设置给PathClassLoader的pathList的dexElements属性。这样就可以在App中通过类路径直接获取Class了。这就是动态加载dex的基本原理。

Dex动态加载

反射获取Field的方法代码:

    /**
     * 获取Class中指定名称的属性Field
     * @param clazz Class对象
     * @param fieldName 属性名称
     * @return 属性Field对象
     * @throws NoSuchFieldException 如果未查找到对应属性,则抛出
     */
    private Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
        Field field = null;
        String classStr = clazz.toString();
        //从子类向父类循环查找Field
        while (clazz != null) {
            try {
                Log.i("Test", "parent class = " + clazz);
                field = clazz.getDeclaredField(fieldName);
                if (field != null) {
                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    return field;
                }
            } catch (Exception e) {
                //忽略错误信息
                //e.printStackTrace();
            }
            //获取父类字节码,从父类查找
            clazz = clazz.getSuperclass();
        }

        //如果未查找到,则抛出异常
        if (field == null) {
            throw new NoSuchFieldException("field: " + fieldName + " not in " + classStr);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值