精华内容
下载资源
问答
  • 一、不同版本的 DEX 加载、 1、Android 8.0 版本 DEX 加载分析、 2、Android 6.0 版本 DEX 加载分析、 3、Android 5.0 版本 DEX 加载分析





    一、不同版本的 DEX 加载



    不同 Android 版本 DexPathList 中的 Element[] dexElements 成员如何创建 ;



    1、Android 8.0 版本 DEX 加载分析


    Android 8.0 8.0 8.0 版本 DEX 加载分析 :

    在 DexPathList 中 , Element[] dexElements 成员创建是调用 makePathElements 方法 生成上述 DEX 数组 ; makeDexElements 方法有 4 4 4 个参数 ;

    8.0 8.0 8.0 系统 Element[] dexElements 生成 代码示例如下 : ( 只展示相关源码 )

    /*package*/ final class DexPathList {
        /**
         * dex/resource (class path) 元素集合.
         * 应该调用 pathElements , 但是 Facebook 应用通过反射修改 dexElements .
         */
        private final Element[] dexElements;
        public DexPathList(ClassLoader definingContext, String dexPath,
                String libraryPath, File optimizedDirectory) {
            // save dexPath for BaseDexClassLoader
            this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
                                               suppressedExceptions, definingContext);
    	}
    }
    

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



    2、Android 6.0 版本 DEX 加载分析


    Android 6.0 6.0 6.0 版本 DEX 加载分析 :

    在 DexPathList 中 , Element[] dexElements 成员创建是调用 makePathElements 方法 生成上述 DEX 数组 ;

    6.0 6.0 6.0 系统 Element[] dexElements 生成 代码示例如下 : ( 只展示相关源码 )

    /*package*/ final class DexPathList {
        /**
         * dex/resource (class path) 元素集合.
         * 应该调用 pathElements , 但是 Facebook 应用通过反射修改 dexElements .
         */
        private final Element[] dexElements;
        public DexPathList(ClassLoader definingContext, String dexPath,
                String libraryPath, File optimizedDirectory) {
            // save dexPath for BaseDexClassLoader
            this.dexElements = makePathElements(splitDexPath(dexPath), optimizedDirectory,
                                                suppressedExceptions);
    	}
    }
    

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



    3、Android 5.0 版本 DEX 加载分析


    Android 5.0 5.0 5.0 版本 DEX 加载分析 :

    在 DexPathList 中 , Element[] dexElements 成员创建是调用 makeDexElements 方法 生成上述 DEX 数组 ; makeDexElements 方法有 3 3 3 个参数 ;

    5.0 5.0 5.0 系统 Element[] dexElements 生成 代码示例如下 : ( 只展示相关源码 )

    /*package*/ final class DexPathList {
        /**
         * dex/resource (class path) 元素集合.
         * 应该调用 pathElements , 但是 Facebook 应用通过反射修改 dexElements .
         */
        private final Element[] dexElements;
        public DexPathList(ClassLoader definingContext, String dexPath,
                String libraryPath, File optimizedDirectory) {
            this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
                                               suppressedExceptions);
    	}
    }
    

    参考源代码 : 5.1.0_r3/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java



    分析上面 3 3 3 个版本的 DEX 加载源码 , 发现每个版本加载方法不同 , 这样在开发多 DEX 加载时 , 就需要做相应的兼容 ;

    展开全文
  • https://blog.csdn.net/qq_18983205/article/details/82748611 对应代码,实现安卓的多 dex 加载dex 加解密
  • 一、65535 方法数限制和 MultiDex 配置、 二、多 DEX 加载引入、 三、PathClassLoader 类加载源码分析、 四、BaseDexClassLoader 类加载源码分析、 五、DexPathList 相关载源码分析、 六、多 DEX 存放位置





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



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

    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.0 5.0 之前的版本 , 应用中只能使用单个 classes.dex , 5.0 5.0 5.0 及以后的版本 原生支持多个 classes.dex 文件 ;

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

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


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





    二、多 DEX 加载引入



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


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

    在这里插入图片描述

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


    常用的 ClassLoader 是 PathClassLoaderDexClassLoader ;

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

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

    源码参考 :





    三、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 3 3 个 DEX 文件 , 那么该数组就有 3 3 3 个元素 ;

    然后 获取该 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 数组中 ;

    展开全文
  • dex加载及替换

    2018-01-31 14:27:39
    不落地dex加载 android系统各函数之间的调用真是很复杂,想直接从源码上看懂基本不肯能。 DexClassLoader可以加载任何路径的apk/dex/jar PathClassLoader只能加载/data/app中的apk,也就是已经安装到手机中的apk...

    不落地dex加载
    android系统各函数之间的调用真是很复杂,想直接从源码上看懂基本不肯能。
    DexClassLoader可以加载任何路径的apk/dex/jar
    PathClassLoader只能加载/data/app中的apk,也就是已经安装到手机中的apk。
    这里写图片描述

    这里写图片描述

    这里写图片描述
    这里写图片描述

    dex映射 方式
    这里写图片描述

    这里写图片描述
    这里写图片描述

    这里据说c层的函数会调用到mmap进行内存映射,不过全局搜索不好用,没搜出来,算了。
    这个函数好像还能进行一般文件的读取,比方说调试标志为的读取,用作反调试。
    尼古拉赵四

    展开全文
  • 【分析】多dex加载机制

    万次阅读 2015-03-27 00:06:45
    下面是多dex加载的时序图:  Android项目有两种方式支持多dex: 1. 项目中的Application类继承MultiDexApplication。 2. 在自己的Application类的attachBaseContext方法中调用MultiDex.install(this);。 我...

    相关文章链接:

    构造多dex的apk

    ---------------------------------------------------------------------------------

    Android源码版本:5.0.2_r1


    下面是多dex加载的时序图: 



    Android项目有两种方式支持多dex:

    1. 项目中的Application类继承MultiDexApplication
    2. 在自己的Application类的attachBaseContext方法中调用MultiDex.install(this);


    我从MultiDexApplication这个类开始分析。


    MultiDexApplication类继承了Application,并重载了attachBaseContext方法,在这个方法中调用了MultiDex.install(this);

    public class MultiDexApplication extends Application {
      @Override
      protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
      }
    }

    MultiDex.install方法:

    /**
     * Patches the application context class loader by appending extra dex files
     * loaded from the application apk. This method should be called in the
     * attachBaseContext of your {@link Application}, see
     * {@link MultiDexApplication} for more explanation and an example.
     *
     * @param context application context.
     * @throws RuntimeException if an error occurred preventing the classloader
     *         extension.
     */
    public static void install(Context context) {
        Log.i(TAG, "install");
    
        ......
    
        try {
            ApplicationInfo applicationInfo = getApplicationInfo(context);
            if (applicationInfo == null) {
                // Looks like running on a test Context, so just return without patching.
                return;
            }
    
            synchronized (installedApk) {
                String apkPath = applicationInfo.sourceDir;
                // installedApk的类型是:Set<String>。
                // 如果这个apk已经安装,则不重复安装。
                if (installedApk.contains(apkPath)) {
                    return;
                }
                installedApk.add(apkPath);
    
                ......
    
                // 类加载器应该直接或间接继承于BaseDexClassLoader。
                // 修改BaseDexClassLoader类中的DexPathList pathList字段,追加额外的DEX文件项。
                /* The patched class loader is expected to be a descendant of
                 * dalvik.system.BaseDexClassLoader. We modify its
                 * dalvik.system.DexPathList pathList field to append additional DEX
                 * file entries.
                 */
                ClassLoader loader;
    
                ......
    
                // dex将会输出到SECONDARY_FOLDER_NAME目录。
                File dexDir = new File(applicationInfo.dataDir, SECONDARY_FOLDER_NAME);
                List<File> files = MultiDexExtractor.load(context, applicationInfo, dexDir, false);
                // 校验这些zip文件是否合法。
                if (checkValidZipFiles(files)) {
                    // 安装提取出来的zip文件。
                    installSecondaryDexes(loader, dexDir, files);
                } else {
                    Log.w(TAG, "Files were not valid zip files.  Forcing a reload.");
                    // 最后一个参数是true,代表强制加载。
                    // Try again, but this time force a reload of the zip file.
                    files = MultiDexExtractor.load(context, applicationInfo, dexDir, true);
    
                    // 校验这些zip文件是否合法。
                    if (checkValidZipFiles(files)) {
                        // 安装提取出来的zip文件。
                        installSecondaryDexes(loader, dexDir, files);
                    } else {
                        // Second time didn't work, give up
                        throw new RuntimeException("Zip files were not valid.");
                    }
                }
            }
    
        } catch (Exception e) {
            Log.e(TAG, "Multidex installation failure", e);
            throw new RuntimeException("Multi dex installation failed (" + e.getMessage() + ").");
        }
        Log.i(TAG, "install done");
    }

    MultiDexExtractor.load获得/导出apk中多出的dex,这些dex导出后会被打包成zip文件:

    /**
     * 提取/获得apk中多dex的提取zip文件。
     * 如果不是加载已经存在的文件的情况,则还要保存apk的信息:时间戳、crc值、apk中dex的总个数。
     * 
     * Extracts application secondary dexes into files in the application data
     * directory.
     *
     * @return a list of files that were created. The list may be empty if there
     *         are no secondary dex files.
     * @throws IOException if encounters a problem while reading or writing
     *         secondary dex files
     */
    static List<File> load(Context context, ApplicationInfo applicationInfo, File dexDir,
            boolean forceReload) throws IOException {
        Log.i(TAG, "MultiDexExtractor.load(" + applicationInfo.sourceDir + ", " + forceReload + ")");
        final File sourceApk = new File(applicationInfo.sourceDir);
    
        long currentCrc = getZipCrc(sourceApk);
    
        List<File> files;
        // isModified方法判断apk是否被修改过。
        if (!forceReload && !isModified(context, sourceApk, currentCrc)) {
            try {
                // 加载已经存在的文件,如果有的文件不存在,或者不是zip文件,则会抛出异常。
                files = loadExistingExtractions(context, sourceApk, dexDir);
            } catch (IOException ioe) {
                Log.w(TAG, "Failed to reload existing extracted secondary dex files,"
                        + " falling back to fresh extraction", ioe);
                // 从apk中提取出多dex,然后将这些dex逐个打包为zip文件,最终返回提取出来的zip文件列表。
                files = performExtractions(sourceApk, dexDir);
                // getTimeStamp方法中调用的是sourceApk.lastModified()方法。
                // putStoredApkInfo方法存储apk的信息:时间戳、crc值、apk中dex的总个数。
                putStoredApkInfo(context, getTimeStamp(sourceApk), currentCrc, files.size() + 1);
    
            }
        } else {
            Log.i(TAG, "Detected that extraction must be performed.");
            // 这里的performExtractions和putStoredApkInfo同上。
            files = performExtractions(sourceApk, dexDir);
            putStoredApkInfo(context, getTimeStamp(sourceApk), currentCrc, files.size() + 1);
        }
    
        Log.i(TAG, "load found " + files.size() + " secondary dex files");
        return files;
    }

    MultiDexExtractor.performExtractions方法:

    /**
     * 从apk中提取出多dex,然后将这些dex逐个打包为zip文件。
     * @param sourceApk apk文件。
     * @param dexDir 输出目录。
     * @return 提取出来的zip文件列表。
     */
    private static List<File> performExtractions(File sourceApk, File dexDir)
            throws IOException {
    
        final String extractedFilePrefix = sourceApk.getName() + EXTRACTED_NAME_EXT;
    
        // 如果文件没有正确的前缀,则删除。
        // Ensure that whatever deletions happen in prepareDexDir only happen if the zip that
        // contains a secondary dex file in there is not consistent with the latest apk.  Otherwise,
        // multi-process race conditions can cause a crash loop where one process deletes the zip
        // while another had created it.
        prepareDexDir(dexDir, extractedFilePrefix);
    
        List<File> files = new ArrayList<File>();
    
        final ZipFile apk = new ZipFile(sourceApk);
        try {
    
            int secondaryNumber = 2;
    
            ZipEntry dexFile = apk.getEntry(DEX_PREFIX + secondaryNumber + DEX_SUFFIX);
            while (dexFile != null) {
                // 输出的文件名。
                String fileName = extractedFilePrefix + secondaryNumber + EXTRACTED_SUFFIX;
                // 输出的文件。
                File extractedFile = new File(dexDir, fileName);
                files.add(extractedFile);
    
                Log.i(TAG, "Extraction is needed for file " + extractedFile);
                int numAttempts = 0;
                boolean isExtractionSuccessful = false;
                while (numAttempts < MAX_EXTRACT_ATTEMPTS && !isExtractionSuccessful) {
                    numAttempts++;
    
                    // 提取apk中的多dex文件,然后打包成一个zip文件。
                    // Create a zip file (extractedFile) containing only the secondary dex file
                    // (dexFile) from the apk.
                    extract(apk, dexFile, extractedFile, extractedFilePrefix);
    
                    // 验证提取的文件是否是一个zip文件。
                    // Verify that the extracted file is indeed a zip file.
                    isExtractionSuccessful = verifyZipFile(extractedFile);
    
                    // Log the sha1 of the extracted zip file
                    Log.i(TAG, "Extraction " + (isExtractionSuccessful ? "success" : "failed") +
                            " - length " + extractedFile.getAbsolutePath() + ": " +
                            extractedFile.length());
                    if (!isExtractionSuccessful) {
                        // Delete the extracted file
                        extractedFile.delete();
                        if (extractedFile.exists()) {
                            Log.w(TAG, "Failed to delete corrupted secondary dex '" +
                                    extractedFile.getPath() + "'");
                        }
                    }
                }
                if (!isExtractionSuccessful) {
                    throw new IOException("Could not create zip file " +
                            extractedFile.getAbsolutePath() + " for secondary dex (" +
                            secondaryNumber + ")");
                }
                secondaryNumber++;
                dexFile = apk.getEntry(DEX_PREFIX + secondaryNumber + DEX_SUFFIX);
            }
        } finally {
            try {
                apk.close();
            } catch (IOException e) {
                Log.w(TAG, "Failed to close resource", e);
            }
        }
    
        return files;
    }

    MultiDexExtractor.putStoredApkInfo方法:

    private static void putStoredApkInfo(Context context, long timeStamp, long crc,
            int totalDexNumber) {
        SharedPreferences prefs = getMultiDexPreferences(context);
        SharedPreferences.Editor edit = prefs.edit();
        edit.putLong(KEY_TIME_STAMP, timeStamp);    // 时间戳
        edit.putLong(KEY_CRC, crc); // crc值。
        /* SharedPreferences.Editor doc says that apply() and commit() "atomically performs the
         * requested modifications" it should be OK to rely on saving the dex files number (getting
         * old number value would go along with old crc and time stamp).
         */
        edit.putInt(KEY_DEX_NUMBER, totalDexNumber);    // dex总个数。
        apply(edit);
    }

    MultiDex.installSecondaryDexes方法,对dex进行安装:

    private static void installSecondaryDexes(ClassLoader loader, File dexDir, List<File> files)
            throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
            InvocationTargetException, NoSuchMethodException, IOException {
        // 安装。
        if (!files.isEmpty()) {
            if (Build.VERSION.SDK_INT >= 19) {
                V19.install(loader, files, dexDir);
            } else if (Build.VERSION.SDK_INT >= 14) {
                V14.install(loader, files, dexDir);
            } else {
                V4.install(loader, files);
            }
        }
    }

    这个方法的代码非常简单,挑选 V19.install分析:

    /**
     * 安装多dex。
     * @param loader 
     * @param additionalClassPathEntries zip文件列表,这些zip文件中都只有一个文件classes.dex。
     * @param optimizedDirectory 优化的dex存放的目录。
     */
    private static void install(ClassLoader loader, List<File> additionalClassPathEntries,
            File optimizedDirectory)
                    throws IllegalArgumentException, IllegalAccessException,
                    NoSuchFieldException, InvocationTargetException, NoSuchMethodException {
        // 被打补丁的类加载器应该直接或间接继承BaseDexClassLoader。
        // 我们修改DexPathList pathList字段,追加额外的DEX文件项。
        /* The patched class loader is expected to be a descendant of
         * dalvik.system.BaseDexClassLoader. We modify its
         * dalvik.system.DexPathList pathList field to append additional DEX
         * file entries.
         */
        // dexPathList = load.pathList;
        Field pathListField = findField(loader, "pathList");
        Object dexPathList = pathListField.get(loader);
    
        ArrayList<IOException> suppressedExceptions = new ArrayList<IOException>();
        // makeDexElements方法调用了DexPathList中的makeDexElements方法,这个方法可以加载并优化dex、zip、jar。
        // expandFieldArray方法将makeDexElements返回的数组patch到dexPathList.dexElements中。
        expandFieldArray(dexPathList, "dexElements", makeDexElements(dexPathList,
                new ArrayList<File>(additionalClassPathEntries), optimizedDirectory,
                suppressedExceptions));
    
        ......
    }

    V19.makeDexElements方法:

    /**
     * A wrapper around
     * {@code private static final dalvik.system.DexPathList#makeDexElements}.
     */
    private static Object[] makeDexElements(
            Object dexPathList, ArrayList<File> files, File optimizedDirectory,
            ArrayList<IOException> suppressedExceptions)
                    throws IllegalAccessException, InvocationTargetException,
                    NoSuchMethodException {
        Method makeDexElements =
                findMethod(dexPathList, "makeDexElements", ArrayList.class, File.class,
                        ArrayList.class);
    
        // return (DexPathList.Element[]) dexPathList.makeDexElements(files, optimizedDirectory, suppressedExceptions)
        return (Object[]) makeDexElements.invoke(dexPathList, files, optimizedDirectory,
                suppressedExceptions);
    }

    MultiDex.expandFieldArray方法:

    /**
     * 原字段内容加上扩展的数组元素替换相应字段的内容,这个字段是一个数组。
     * 
     * Replace the value of a field containing a non null array, by a new array containing the
     * elements of the original array plus the elements of extraElements.
     * @param instance the instance whose field is to be modified.
     * @param fieldName the field to modify.
     * @param extraElements elements to append at the end of the array.
     */
    private static void expandFieldArray(Object instance, String fieldName,
            Object[] extraElements) throws NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        // combined = new <Type>[original.length + extraElements.length];
        Field jlrField = findField(instance, fieldName);
        Object[] original = (Object[]) jlrField.get(instance);
        Object[] combined = (Object[]) Array.newInstance(
                original.getClass().getComponentType(), original.length + extraElements.length);
    
        System.arraycopy(original, 0, combined, 0, original.length);
        System.arraycopy(extraElements, 0, combined, original.length, extraElements.length);
        // 替换对象中的数组字段。
        jlrField.set(instance, combined);
    }


    展开全文
  • 插件Apk Dex加载机制

    2018-10-12 15:10:37
    ClassLoader简介 ...对于自定义动态加载dex文件,我们可以通过DexClassLoader来实现jar、dex、apk等文件格式加载,其父类都是BaseClassLoader,实现了对文件加载、verify、optimize等动作,最后生...
  • 在看雪发了,52再发一下,共同学习菜鸟刚刚学完了dex_file.cc这个源码,大致搞明白了大佬们hook脱整体加固的原理了,原理在帖子最后学习了大佬...总结的很清晰,dex 加载到内存之后,只要想方设法找到DexFil...
  • 上一篇插件化知识详细分解及原理 之代理,hook,反射,接着上篇我们说ClassLoader和dex加载过程 为了解决65535这个问题,Google提出了multidex方案,即一个apk文件可以包含多个dex文件。 不过值得注意的是,除了第...
  • 文章目录Android APK加固-安全人员角度关于类加载器类加载器类加载器的种类和个数创建类加载实例类加载器DexClassLoader和PathClassLoader使用类加载器动态加载dex文件制作dex文件动态加载dex文件完整步骤回顾 ...
  • (十三)Dex 加解密与多 Dex 加载

    千次阅读 2018-11-06 16:09:14
    版权声明:本文为博主原创文章,...一个安卓 apk 里面包含有 AndroidManifest.xml、classes.dex、resources.arsc 等文件,java 代码主要存在于 classes.dex 中。 把 classes.dex 文件拆分为两个 dex 文件,其中主 d...
  • Dex加载方案对比

    千次阅读 2018-07-02 13:34:16
    随着业务扩张,代码量越来越大,apk中单个dex方法数超过65K,就需要dex分包,Google官方推出了MultiDex来解决65K的问题,区分不同的Android虚拟机,会有一些问题。 Dalvik上,使用JIT(just in time),应用运行时,...
  • 7.1的内存加载(直接从byte字节数据加载,自构造内存DexFile后,还是过不了defineclassNative这一关,总是报错Check failed: dex_cache_location == dex_file_suffix (dex_cache_location=ςက, dex_file_suffix=�@,...
  • android dex加载跟踪

    2017-02-22 00:57:29
    Dalvik_dalvik_system_DexFile_openDexFile_bytearray() => /dalvik/vm/native/dalvik_system_DexFile.cpp dvmRawDexFileOpenArray() => /dalvik/vm/RawDexFile.cpp dvmPrepareDexInMemory() => /dalvik/vm/...
  • Android系统下的动态Dex加载

    千次阅读 2014-10-31 10:37:10
    在Android系统中,一个App的所有代码都在一个Dex文件里面。Dex是一个类似Jar的存 储了多有Java编译字节码的归档文件。因为Android系统使用Dalvik虚拟机,所以需要把 使用Java Compiler编译之后的class文件转换成...
  • 重要提示:此库已被 buildToolsVersion 21.1.0 取代 如果您使用的是 21.1.0 或更高版本,则多索引的步骤是: android { compileSdkVersion 21 buildToolsVersion "21.1.0" defaultConfig { ...
  • Android dex加载过程分析

    千次阅读 2016-08-10 22:30:26
    自然DexClassLoader调用的就是DexFile.loadDex(file.getPath(), optimizedPath, 0); 先看loadDex static public DexFile loadDex(String sourcePathName, String outputPathName, int flags) throws ...
  • Android系统下的Dex加载

    2016-02-03 14:01:08
    在Android系统中,一个App的所有代码都在一个Dex文件里面。Dex是一个类似Jar的存 储了多有Java编译字节码的归档文件。因为Android系统使用Dalvik虚拟机,所以需要把 使用Java Compiler编译之后的class文件转换成...
  • 在Android源码中,DexFile中有一个openDexFile方法,就是通过byte数组加载一个Dex,可以达到秒级加载,亲自测了下,如果一个使用Multidex加载的App,第二个Dex如果需要加载耗时2s+,则使用这个函数去加载,只需要300...
  • 什么是64K限制和LinearAlloc限制64K限制随着Android应用功能的增加,代码量不断地增大,当应用方法数量超过了65536的时候,编译的时候便会提示:这个Android著名的Dex 64k method数量上限。那么,是什么原因导致方法...
  • 更新这适用于Dalvik和ART:新的DexClassLoader(jarredDex.getAbsolutePath(),context.getDir(“outdex”,Context.MODE_PRIVATE).getAbsolutePath(),...其中jarredDex是一个带有classes.dex的jar文件. Jar可以通过运...
  • 在Android系统中,一个App的所有代码都在一个Dex文件里面。Dex是一个类似Jar的存储了多有Java编译字节码的归档文件。因为Android系统使用Dalvik虚拟机,所以需要把 使用Java Compiler编译之后的class文件转换成...
  • 2019独角兽企业重金招聘Python工程师标准>>> class加载原理和Dex加载的原理 转载于:https://my.oschina.net/quguangle/blog/1569772

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,061
精华内容 8,824
关键字:

dex加载