1. 程式人生 > >絕望的DexMaker學習之路(一)——DexMaker類的generateAndLoad函式

絕望的DexMaker學習之路(一)——DexMaker類的generateAndLoad函式

目前好像並沒有很多關於Dexmaker類的原始碼解析,所以公開了這篇部落格。我的Dexmaker庫學習之路在看到生成註解的類的原始碼時走到了盡頭,不過也許會隨著原始碼的完善而繼續下去也說不準

一.原始碼

public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException {
        if (dexCache == null) {
            String property = System.getProperty("dexmaker.dexcache");
            if (property != null) {
                dexCache = new File(property);
            } else {
                dexCache = new AppDataDirGuesser().guess();
                if (dexCache == null) {
                    throw new IllegalArgumentException("dexcache == null (and no default could be"
                            + " found; consider setting the 'dexmaker.dexcache' system property)");
                }
            }
        }

        File result = new File(dexCache, generateFileName());
        // Check that the file exists. If it does, return a DexClassLoader and skip all
        // the dex bytecode generation.
        if (result.exists()) {
            return generateClassLoader(result, dexCache, parent);
        }

        byte[] dex = generate();

        /*
         * This implementation currently dumps the dex to the filesystem. It
         * jars the emitted .dex for the benefit of Gingerbread and earlier
         * devices, which can't load .dex files directly.
         *
         * TODO: load the dex from memory where supported.
         */
        result.createNewFile();
        JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
        JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME);
        entry.setSize(dex.length);
        jarOut.putNextEntry(entry);
        jarOut.write(dex);
        jarOut.closeEntry();
        jarOut.close();
        return generateClassLoader(result, dexCache, parent);
    }

二.該函式的執行機制

第一次成功運行了demo之後,我更改了demo中變數的值,觀察到發現打印出的值沒有變化。

下面我們來探究一下為什麼會出現這個問題:

通過斷點除錯,我發現,在生成dex檔案之前會先生成一個jar檔案

然後判斷是否已經存在,如果不是第一次執行這個程式,result.exsits()的結果就會是true,然後執行圖中的這個語句,用之前生成的jar檔案進行下一步的操作

下面我們來進一步看一下result.exists(),這個函式呼叫了StrictMode.java中的一個函式

接下來,該怎樣解決這個問題呢?

最初的想法是重寫這個函式,但是原始碼中的DexMaker類被定義成了final的。並且,生成jar檔案的檔名的函式也是在DexMaker中定義的,所以我們也不能通過加個隨機數的方法每次生成不同的檔名。那麼就只剩了一個辦法,每次重新生成之前先清除資料夾中之前生成的檔案。