目前好像并没有很多关于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文件(此时这个jar文件是没有后期生成的dex文件的内容的,dex文件的内容是后面写入到这个jar文件中的)
然后判断是否已经存在,如果不是第一次运行这个程序,result.exsits()的结果就会是true,然后执行图中的这个语句,用之前生成的jar文件进行下一步的操作
下面我们来进一步看一下result.exists(),这个函数调用了StrictMode.java中的一个函数
接下来,该怎样解决这个问题呢?
最初的想法是重写这个函数,但是源码中的DexMaker类被定义成了final的。并且,生成jar文件的文件名的函数也是在DexMaker中定义的,所以我们也不能通过加个随机数的方法每次生成不同的文件名。那么就只剩了一个办法,每次重新生成之前先清除文件夹中之前生成的文件。