絕望的DexMaker學習之路(一)——DexMaker類的generateAndLoad函式
阿新 • • 發佈:2018-12-17
目前好像並沒有很多關於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中定義的,所以我們也不能通過加個隨機數的方法每次生成不同的檔名。那麼就只剩了一個辦法,每次重新生成之前先清除資料夾中之前生成的檔案。