【Android 安全】DEX 加密 ( 多 DEX 加载 | 65535 方法数限制和 MultiDex 配置 | PathClassLoader 类加载源码分析 | DexPathList )

简介: 【Android 安全】DEX 加密 ( 多 DEX 加载 | 65535 方法数限制和 MultiDex 配置 | PathClassLoader 类加载源码分析 | DexPathList )

文章目录

一、65535 方法数限制和 MultiDex 配置

二、多 DEX 加载引入

三、PathClassLoader 类加载源码分析

四、BaseDexClassLoader 类加载源码分析

五、DexPathList 相关载源码分析

六、多 DEX 存放位置





一、65535 方法数限制和 MultiDex 配置


在 Android 开发中 , 尤其是项目比较大时 , 或引入的依赖库过多 , 一般的项目后期都会遇到 如下问题 , 整个工程的方法数超过了 65535 6553565535 个 , 编译时报如下错误 :


trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536


Google 官方给出了解决方案 : https://developer.android.google.cn/studio/build/multidex.html



5.0 5.05.0 之前的版本 , 应用中只能使用单个 classes.dex , 5.0 5.05.0 及以后的版本 原生支持多个 classes.dex 文件 ;


如果最低版本号大于等于 21 2121 , 就可以不用配置 MultiDex ;


反之版本号小于 21 2121 , 则 必须进行 MultiDex 配置 ;



Google 提供的 com.android.support:multidex 库 , 就是为了兼容 5.0 5.05.0 之前的版本 ;






二、多 DEX 加载引入


MultiDexApplication 中就使用 Android 中的类加载机制 , ClassLoader 加载机制 ;



ClassLoader 相关源码在 libcore/dalvik/src/main/java/dalvik/system Android 源码目录下 ,




参考 : libcore/dalvik/src/main/java/dalvik/system



常用的 ClassLoader 是 PathClassLoader 和 DexClassLoader ;


PathClassLoader 只能加载 已安装 apk 的 dex ;


DexClassLoader 可以加载 已安装 或 文件系统 中的 APK , DEX , JAR ;


源码参考 :


PathClassLoader : libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
DexClassLoader : libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java





三、PathClassLoader 类加载源码分析


在 Android 中使用的是 PathClassLoader , 该类很简单 , 只是单纯的继承 BaseDexClassLoader ,


package dalvik.system;
public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }
    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}


参考源码地址 : libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java






四、BaseDexClassLoader 类加载源码分析


BaseDexClassLoader 是通过 Class<?> findClass(String name) 方法查找类的 , 给定一个全类名字符串 , 返回字节码 ,


查找类通过调用 pathList 的 findClass 方法 , 获取字节码文件 ,


pathList 对应的成员变量定义是 DexPathList pathList , 它是 DexPathList 类型的 ,


public class BaseDexClassLoader extends ClassLoader {
    private final DexPathList pathList;
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
        Class c = pathList.findClass(name, suppressedExceptions);
        if (c == null) {
            ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);
            for (Throwable t : suppressedExceptions) {
                cnfe.addSuppressed(t);
            }
            throw cnfe;
        }
        return c;
    }
}


参考源码地址 : libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java






五、DexPathList 相关载源码分析


DexPathList 的 findClass 方法 , 主要是遍历 Element[] dexElements 成员 ,


Element[] dexElements 数组中保存的就是内存中的 DEX 文件 , 如果 APP 中有 3 33 个 DEX 文件 , 那么该数组就有 3 33 个元素 ;


然后 获取该 element 中的 dexFile , 这是 DexFile 类型文件 ,


调用 DexFile 的 loadClassBinaryName 加载对应的类 ,


/*package*/ final class DexPathList {
    /**
     * dex/resource (class path) 元素集合.
     * 应该调用 pathElements , 但是 Facebook 应用通过反射修改 dexElements .
     */
    private final Element[] dexElements;
    public Class findClass(String name, List<Throwable> suppressed) {
        for (Element element : dexElements) {
            DexFile dex = element.dexFile;
            if (dex != null) {
                Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
                if (clazz != null) {
                    return clazz;
                }
            }
        }
        if (dexElementsSuppressedExceptions != null) {
            suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
        }
        return null;
    }
}


参考源码地址 : libcore/dalvik/src/main/java/dalvik/system/DexPathList.java






六、多 DEX 存放位置


上述 DexPathList 中的 Element[] dexElements 成员就保存了当前应用中的 DEX 文件 ,


再次回到 classes.dex 分割的问题上 , 如果我们设置一个主 DEX , 其中只存在代理 Application , 用于解密其它被加密的 DEX , 其它的 DEX 都是被加密的 ;


这些 DEX 文件 都需要被存放到上述 DexPathList 的 Element[] dexElements 数组中 ;


目录
相关文章
|
开发工具 Android开发 iOS开发
如何在Android Studio中配置Flutter环境?
如何在Android Studio中配置Flutter环境?
2853 160
|
8月前
|
存储 API Android开发
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
735 4
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
|
8月前
|
Java 开发工具 Maven
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
979 6
|
9月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1430 10
|
11月前
|
安全 Java 数据库
Jasypt加密数据库配置信息
本文介绍了使用 Jasypt 对配置文件中的公网数据库认证信息进行加密的方法,以提升系统安全性。主要内容包括:1. 背景介绍;2. 前期准备,如依赖导入及版本选择;3. 生成密钥并实现加解密测试;4. 在配置文件中应用加密后的密码,并通过测试接口验证解密结果。确保密码安全的同时,保障系统的正常运行。
769 3
Jasypt加密数据库配置信息
|
10月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1554 1
|
11月前
|
存储 安全 Cloud Native
云原生安全必修课:RDS透明加密(TDE)与数据脱敏联动实施方案
云原生环境下,数据泄露风险日益严峻,传统安全方案面临加密与脱敏割裂、保护不连续、权限控制粗放三大挑战。本方案融合TDE透明加密与动态数据脱敏技术,构建存储-传输-计算全链路防护体系,通过SQL级加密与角色化脱敏规则,实现细粒度数据保护。结合密钥管理、权限控制与多云适配,提升安全性与性能,广泛适用于金融、医疗等高安全要求场景。
407 3
|
10月前
|
安全 算法 量子技术
量子来了,DeFi慌了吗?——聊聊量子安全加密对去中心化金融的“革命冲击”
量子来了,DeFi慌了吗?——聊聊量子安全加密对去中心化金融的“革命冲击”
288 0
|
存储 安全 数据安全/隐私保护
Hyper V文件复制安全:加密与访问控制
在Hyper-V环境中,确保文件复制的安全性至关重要。主要措施包括:启用数据加密、使用HTTPS协议和磁盘加密技术(如BitLocker)保护数据传输和存储;通过身份验证、权限管理和审核日志控制访问;定期更新补丁、实施网络隔离及制定备份恢复策略。这些多层次的安全措施共同防止未经授权的访问和数据泄露,保障数据安全。
Hyper V文件复制安全:加密与访问控制