转载请注明出处:http://blog.csdn.net/llew2011/article/details/78628613
前边两篇文章Android 源码系列之<十七>自定义Gradle Plugin,优雅的解决第三方Jar包中的bug<上>和Android 源码系列之<十八>自定义Gradle Plugin,优雅的解决第三方Jar包中的bug<中>里主要讲解了如何自定义Gradle Plugin,然后利用自定义的Gradle Plugin插件来修复项目中引用的第三方Jar包中的bug的方法,其核心就是利用开源库Javassist修复第三方Jar包中的class文件,然后在项目打包的时候把修复过的Jar包打包进项目中从而达到修复的目的。如果有小伙伴还没看过前两篇文章,强烈建议阅读一下。这篇文章我们就从源码的角度深入理解一下Javassist库是如何修复class文件的(*^__^*) ……
阅读开源代码,一般都是从使用开始,记得在上篇文章中我们是如何使用Javassist库的么?首先是初始化了ClassPool对象sClassPool,代码如下:
public static void init(Project project, String versionName, BytecodeFixExtension extension) {
sClassPool = ClassPool.default
sInjector = new BytecodeFixInjector(project, versionName, extension)
}
在BytecodeFixInjector的init()方法中通过ClassPool的静态方法getDefault()返回一个ClassPool对象然后赋值给了sClassPool,ClassPool是做什么工作的?它的职责是什么?根据名字像是一个对象池,既然是对象池,应该像数据库连接池一样能提供对象的哈,这是我第一次接触它的时候猜测的,我们看一下ClassPool的说明:
A container of CtClass objects. A CtClass object must be obtained from this object. If get() is called on this object, it searches various sources represented by ClassPath to find a class file and then it creates a CtClass object representing that class file. The created object is returned to the caller.
【译】ClassPool是CtClass的容器,每一个CtClass对象都必须从ClassPool中获取。如果调用了ClassPool的get()方法,那么ClassPool就会搜索由ClassPath指定的不同资源去找到一个class文件然后ClassPool就会创建一个CtClass对象,该对象就代表着那个.class文件。最后ClassPool创建的CtClass对象会返回给调用者。
ClassPool objects hold all the CtClasses that have been created so that the consistency among modified classes can be guaranteed. Thus if a large number of CtClasses are processed, the ClassPool will consume a huge amount of memory. To avoid this, a ClassPool object should be recreated, for example, every hundred classes processed. Note that getDefault() is a singleton factory. Otherwise, detach() in CtClass should be used to avoid huge memory consumption.
【译】ClassPool持有所有创建的CtClass对象,因此修改类的话,它们之间的一致性可以得到保证。因此,如果处理大量的CtClass类,ClassPool将要消耗大量的内存,为了避免这种情况,应该重新创建ClassPool对象,例如,每次都要处理成千上百的class类。注意,getDefault()方法是一个单例模式的工厂方法,因此,应该调用detach()方法来避免大量的内存消耗。
ClassPools can make a parent-child hierarchy as java.lang.ClassLoaders. If a ClassPool has a parent pool, get() first asks the parent pool to find a class fil