[jboss-cvs] javassist/src/main/javassist ...

Shigeru Chiba chiba at is.titech.ac.jp
Fri Jun 8 09:32:10 EDT 2007


  User: chiba   
  Date: 07/06/08 09:32:10

  Modified:    src/main/javassist          CtNewClass.java CtClassType.java
                        CtNewWrappedMethod.java CtField.java CtMember.java
                        CtClass.java ClassPool.java CtMethod.java
                        CtConstructor.java
  Log:
  made automatic pruning off by default because I found that pruning does not really save memory (only 20%).  I changed Javassist to compress a class file on memory after toBytecode().
  
  Revision  Changes    Path
  1.12      +0 -1      javassist/src/main/javassist/CtNewClass.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtNewClass.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtNewClass.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -b -r1.11 -r1.12
  --- CtNewClass.java	4 Jun 2007 03:11:11 -0000	1.11
  +++ CtNewClass.java	8 Jun 2007 13:32:10 -0000	1.12
  @@ -28,7 +28,6 @@
                  boolean isInterface, CtClass superclass) {
           super(name, cp);
           wasChanged = true;
  -        eraseCache();
           String superName;
           if (superclass == null)
               superName = null;
  
  
  
  1.57      +294 -211  javassist/src/main/javassist/CtClassType.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtClassType.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtClassType.java,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -b -r1.56 -r1.57
  --- CtClassType.java	4 Jun 2007 03:11:11 -0000	1.56
  +++ CtClassType.java	8 Jun 2007 13:32:10 -0000	1.57
  @@ -15,7 +15,10 @@
   
   package javassist;
   
  +import java.lang.ref.WeakReference;
   import java.io.BufferedInputStream;
  +import java.io.ByteArrayOutputStream;
  +import java.io.ByteArrayInputStream;
   import java.io.DataInputStream;
   import java.io.DataOutputStream;
   import java.io.IOException;
  @@ -60,12 +63,9 @@
       boolean wasPruned;
       boolean memberRemoved;
       ClassFile classfile;
  +    byte[] rawClassfile;    // backup storage
   
  -    private CtMember fieldsCache;
  -    private CtMember methodsCache;
  -    private CtMember constructorsCache;
  -    private CtConstructor classInitializerCache;
  -
  +    private WeakReference memberCache;
       private AccessorMaker accessors;
   
       private FieldInitLink fieldInitializers;
  @@ -76,17 +76,19 @@
       int getCounter;
       private static int readCounter = 0;
       private static final int READ_THRESHOLD = 100;  // see getClassFile2()
  +    private static final int GET_THRESHOLD = 2;     // see releaseClassFiles()
   
       CtClassType(String name, ClassPool cp) {
           super(name);
           classPool = cp;
           wasChanged = wasFrozen = wasPruned = memberRemoved = false;
           classfile = null;
  +        rawClassfile = null;
  +        memberCache = null;
           accessors = null;
           fieldInitializers = null;
           hiddenMethods = null;
           uniqueNumberSeed = 0;
  -        eraseCache();
           getCounter = 0;
       }
   
  @@ -136,36 +138,23 @@
               buffer.append(" extends ??");
           }
   
  -        CtMember field = getFieldsCache();
  -        buffer.append(" fields=");
  -        while (field != null) {
  -            buffer.append(field);
  -            buffer.append(", ");
  -            field = field.next;
  -        }
  -
  -        CtMember c = getConstructorsCache();
  -        buffer.append(" constructors=");
  -        while (c != null) {
  -            buffer.append(c);
  -            buffer.append(", ");
  -            c = c.next;
  +        CtMember.Cache memCache = getMembers();
  +        exToString(buffer, " fields=",
  +                memCache.fieldHead(), memCache.lastField());
  +        exToString(buffer, " constructors=",
  +                memCache.consHead(), memCache.lastCons());
  +        exToString(buffer, " methods=",
  +                   memCache.methodHead(), memCache.lastMethod());
           }
   
  -        CtMember m = getMethodsCache();
  -        buffer.append(" methods=");
  -        while (m != null) {
  -            buffer.append(m);
  +    private void exToString(StringBuffer buffer, String msg,
  +                            CtMember head, CtMember tail) {
  +        buffer.append(msg);
  +        while (head != tail) {
  +            head = head.next();
  +            buffer.append(head);
               buffer.append(", ");
  -            m = m.next;
  -        }
       }
  -
  -    protected void eraseCache() {
  -        fieldsCache = null;
  -        constructorsCache = null;
  -        classInitializerCache = null;
  -        methodsCache = null;
       }
   
       public AccessorMaker getAccessorMaker() {
  @@ -176,15 +165,29 @@
       }
   
       public ClassFile getClassFile2() {
  -        if (classfile != null)
  -            return classfile;
  +        ClassFile cfile = classfile;
  +        if (cfile != null)
  +            return cfile;
   
  -        if (readCounter++ > READ_THRESHOLD
  -                                    && ClassPool.releaseUnmodifiedClassFile) {
  +        if (readCounter++ > READ_THRESHOLD) {
  +            getCounter += 2;
               releaseClassFiles();
               readCounter = 0;
           }
   
  +        if (rawClassfile != null) {
  +            try {
  +                classfile = new ClassFile(new DataInputStream(
  +                                            new ByteArrayInputStream(rawClassfile)));
  +                rawClassfile = null;
  +                getCounter = GET_THRESHOLD;
  +                return classfile;
  +            }
  +            catch (IOException e) {
  +                throw new RuntimeException(e.toString(), e);
  +            }
  +        }
  +
           InputStream fin = null;
           try {
               fin = classPool.openClassfile(getName());
  @@ -192,19 +195,20 @@
                   throw new NotFoundException(getName());
   
               fin = new BufferedInputStream(fin);
  -            classfile = new ClassFile(new DataInputStream(fin));
  -            if (!classfile.getName().equals(qualifiedName))
  +            ClassFile cf = new ClassFile(new DataInputStream(fin));
  +            if (!cf.getName().equals(qualifiedName))
                   throw new RuntimeException("cannot find " + qualifiedName + ": " 
  -                        + classfile.getName() + " found in "
  +                        + cf.getName() + " found in "
                           + qualifiedName.replace('.', '/') + ".class");
   
  -            return classfile;
  +            classfile = cf;
  +            return cf;
           }
           catch (NotFoundException e) {
  -            throw new RuntimeException(e.toString());
  +            throw new RuntimeException(e.toString(), e);
           }
           catch (IOException e) {
  -            throw new RuntimeException(e.toString());
  +            throw new RuntimeException(e.toString(), e);
           }
           finally {
               if (fin != null)
  @@ -215,14 +219,41 @@
           }
       }
   
  +    /**
  +     * Converts a ClassFile object into a byte array
  +     * for saving memory space.
  +     */
  +    public synchronized void saveClassFile() {
  +        /* getMembers() and releaseClassFile() are also synchronized.
  +         */
  +        if (classfile == null || hasMemberCache() != null)
  +            return;
  +
  +        ByteArrayOutputStream barray = new ByteArrayOutputStream();
  +        DataOutputStream out = new DataOutputStream(barray);
  +        try {
  +            classfile.write(out);
  +            barray.close();
  +            rawClassfile = barray.toByteArray();
  +            classfile = null;
  +        }
  +        catch (IOException e) {}
  +    }
  +
  +    public synchronized void releaseClassFile() {
  +        if (!isModified())
  +            classfile = null;
  +    }
  +
       /* Inherited from CtClass.  Called by get() in ClassPool.
        *
        * @see javassist.CtClass#incGetCounter()
  +     * @see #toBytecode(DataOutputStream)
        */
       void incGetCounter() { ++getCounter; }
   
       /**
  -     * Releases the class files and cached CtBehaviors
  +     * Releases the class files
        * of the CtClasses that have not been recently used
        * if they are unmodified. 
        */
  @@ -232,10 +263,11 @@
               Object obj = e.nextElement();
               if (obj instanceof CtClassType) {
                   CtClassType cct = (CtClassType)obj;
  -                if (cct.getCounter < 2 && !cct.isModified()) {
  -                    cct.eraseCache();
  -                    cct.classfile = null;
  -                }
  +                if (cct.getCounter < GET_THRESHOLD)
  +                    if (!cct.isModified() && ClassPool.releaseUnmodifiedClassFile)
  +                        cct.releaseClassFile();
  +                    else if (cct.isFrozen() && !cct.wasPruned)
  +                        cct.saveClassFile();
   
                   cct.getCounter = 0;
               }
  @@ -314,7 +346,7 @@
           ClassFile cf = getClassFile2();
           super.setName(name);
           cf.setName(name);
  -        eraseCache();
  +        nameReplaced();
           classPool.classNameChanged(oldname, this);
       }
   
  @@ -333,7 +365,7 @@
           super.replaceClassName(classnames);
           ClassFile cf = getClassFile2();
           cf.renameClass(classnames);
  -        eraseCache();
  +        nameReplaced();
   
           if (newClassName != null) {
               super.setName(newClassName);
  @@ -350,7 +382,7 @@
           else {
               super.replaceClassName(oldname, newname);
               getClassFile2().renameClass(oldname, newname);
  -            eraseCache();
  +            nameReplaced();
           }
       }
   
  @@ -702,6 +734,69 @@
           return c;
       }
   
  +    /* flush cached names.
  +     */
  +    private void nameReplaced() {
  +        CtMember.Cache cache = hasMemberCache();
  +        if (cache != null) {
  +            CtMember mth = cache.methodHead();
  +            CtMember tail = cache.lastMethod();
  +            while (mth != tail) {
  +                mth = mth.next();
  +                mth.nameReplaced();
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Returns null if members are not cached.
  +     */
  +    protected CtMember.Cache hasMemberCache() {
  +        if (memberCache != null)
  +            return (CtMember.Cache)memberCache.get();
  +        else
  +            return null;
  +    }
  +
  +    protected synchronized CtMember.Cache getMembers() {
  +        CtMember.Cache cache = null;
  +        if (memberCache == null
  +            || (cache = (CtMember.Cache)memberCache.get()) == null) {
  +            cache = new CtMember.Cache(this);
  +            makeFieldCache(cache);
  +            makeBehaviorCache(cache);
  +            memberCache = new WeakReference(cache);
  +        }
  +
  +        return cache;
  +    }
  +
  +    private void makeFieldCache(CtMember.Cache cache) {
  +        List list = getClassFile2().getFields();
  +        int n = list.size();
  +        for (int i = 0; i < n; ++i) {
  +            FieldInfo finfo = (FieldInfo)list.get(i);
  +            CtField newField = new CtField(finfo, this);
  +            cache.addField(newField);
  +        }
  +    }
  +
  +    private void makeBehaviorCache(CtMember.Cache cache) {
  +        List list = getClassFile2().getMethods();
  +        int n = list.size();
  +        for (int i = 0; i < n; ++i) {
  +            MethodInfo minfo = (MethodInfo)list.get(i);
  +            if (minfo.isMethod()) {
  +                CtMethod newMethod = new CtMethod(minfo, this);
  +                cache.addMethod(newMethod);
  +            }
  +            else {
  +                CtConstructor newCons = new CtConstructor(minfo, this);
  +                cache.addConstructor(newCons);
  +            }
  +        }
  +    }
  +
       public CtField[] getFields() {
           ArrayList alist = new ArrayList();
           getFields(alist, this);
  @@ -726,12 +821,13 @@
           }
           catch (NotFoundException e) {}
   
  -        CtMember cf = ((CtClassType)cc).getFieldsCache();
  -        while (cf != null) {
  -            if (!Modifier.isPrivate(cf.getModifiers()))
  -                alist.add(cf);
  -
  -            cf = cf.next;
  +        CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  +        CtMember field = memCache.fieldHead();
  +        CtMember tail = memCache.lastField();
  +        while (field != tail) {
  +            field = field.next();
  +            if (!Modifier.isPrivate(field.getModifiers()))
  +                alist.add(field);
           }
       }
   
  @@ -766,37 +862,20 @@
       }
   
       public CtField[] getDeclaredFields() {
  -        CtMember cf = getFieldsCache();
  -        int num = CtField.count(cf);
  +        CtMember.Cache memCache = getMembers();
  +        CtMember field = memCache.fieldHead();
  +        CtMember tail = memCache.lastField();
  +        int num = CtMember.Cache.count(field, tail);
           CtField[] cfs = new CtField[num];
           int i = 0;
  -        while (cf != null) {
  -            cfs[i++] = (CtField)cf;
  -            cf = cf.next;
  +        while (field != tail) {
  +            field = field.next();
  +            cfs[i++] = (CtField)field;
           }
   
           return cfs;
       }
   
  -    protected CtMember getFieldsCache() {
  -        if (fieldsCache == null) {
  -            List list = getClassFile2().getFields();
  -            int n = list.size();
  -            CtMember allFields = null;
  -            CtField tail = null;
  -            for (int i = 0; i < n; ++i) {
  -                FieldInfo finfo = (FieldInfo)list.get(i);
  -                CtField newTail = new CtField(finfo, this);
  -                allFields = CtMember.append(allFields, tail, newTail);
  -                tail = newTail;
  -            }
  -
  -            fieldsCache = allFields;
  -        }
  -
  -        return fieldsCache;
  -    }
  -
       public CtField getDeclaredField(String name) throws NotFoundException {
           CtField f = getDeclaredField2(name);
           if (f == null)
  @@ -806,115 +885,131 @@
       }
   
       private CtField getDeclaredField2(String name) {
  -        CtMember cf = getFieldsCache();
  -        while (cf != null) {
  -            if (cf.getName().equals(name))
  -                return (CtField)cf;
  -
  -            cf = cf.next;
  +        CtMember.Cache memCache = getMembers();
  +        CtMember field = memCache.fieldHead();
  +        CtMember tail = memCache.lastField();
  +        while (field != tail) {
  +            field = field.next();
  +            if (field.getName().equals(name))
  +                return (CtField)field;
           }
   
           return null;
       }
   
       public CtBehavior[] getDeclaredBehaviors() {
  -        CtMember cc = getConstructorsCache();
  -        CtMember cm = getMethodsCache();
  -        int num = CtMember.count(cm) + CtMember.count(cc);
  -        CtBehavior[] cb = new CtBehavior[num];
  +        CtMember.Cache memCache = getMembers();
  +        CtMember cons = memCache.consHead();
  +        CtMember consTail = memCache.lastCons();
  +        int cnum = CtMember.Cache.count(cons, consTail);
  +        CtMember mth = memCache.methodHead();
  +        CtMember mthTail = memCache.lastMethod();
  +        int mnum = CtMember.Cache.count(mth, mthTail);
  +
  +        CtBehavior[] cb = new CtBehavior[cnum + mnum];
           int i = 0;
  -        while (cc != null) {
  -            cb[i++] = (CtBehavior)cc;
  -            cc = cc.next;
  +        while (cons != consTail) {
  +            cons = cons.next();
  +            cb[i++] = (CtBehavior)cons;
           }
   
  -        while (cm != null) {
  -            cb[i++] = (CtBehavior)cm;
  -            cm = cm.next;
  +        while (mth != mthTail) {
  +            mth = mth.next();
  +            cb[i++] = (CtBehavior)mth;
           }
   
           return cb;
       }
   
       public CtConstructor[] getConstructors() {
  -        CtConstructor[] cons = getDeclaredConstructors();
  -        if (cons.length == 0)
  -            return cons;
  +        CtMember.Cache memCache = getMembers();
  +        CtMember cons = memCache.consHead();
  +        CtMember consTail = memCache.lastCons();
   
           int n = 0;
  -        int i = cons.length;
  -        while (--i >= 0)
  -            if (!Modifier.isPrivate(cons[i].getModifiers()))
  -                ++n;
  +        CtMember mem = cons;
  +        while (mem != consTail) {
  +            mem = mem.next();
  +            if (isPubCons((CtConstructor)mem))
  +                n++;
  +        }
   
           CtConstructor[] result = new CtConstructor[n];
  -        n = 0;
  -        i = cons.length;
  -        while (--i >= 0) {
  -            CtConstructor c = cons[i];
  -            if (!Modifier.isPrivate(c.getModifiers()))
  -                result[n++] = c;
  +        int i = 0;
  +        mem = cons;
  +        while (mem != consTail) {
  +            mem = mem.next();
  +            CtConstructor cc = (CtConstructor)mem;
  +            if (isPubCons(cc))
  +                result[i++] = cc;
           }
   
           return result;
       }
   
  +    private static boolean isPubCons(CtConstructor cons) {
  +        return !Modifier.isPrivate(cons.getModifiers())
  +                && cons.isConstructor();
  +    }
  +
       public CtConstructor getConstructor(String desc)
           throws NotFoundException
       {
  -        CtConstructor cc = (CtConstructor)getConstructorsCache();
  -        while (cc != null) {
  -            if (cc.getMethodInfo2().getDescriptor().equals(desc))
  +        CtMember.Cache memCache = getMembers();
  +        CtMember cons = memCache.consHead();
  +        CtMember consTail = memCache.lastCons();
  +
  +        while (cons != consTail) {
  +            cons = cons.next();
  +            CtConstructor cc = (CtConstructor)cons;
  +            if (cc.getMethodInfo2().getDescriptor().equals(desc)
  +                && cc.isConstructor())
                   return cc;
  -
  -            cc = (CtConstructor)cc.next;
           }
   
           return super.getConstructor(desc);
       }
   
       public CtConstructor[] getDeclaredConstructors() {
  -        CtMember cc = getConstructorsCache();
  -        int num = CtMember.count(cc);
  -        CtConstructor[] ccs = new CtConstructor[num];
  -        int i = 0;
  -        while (cc != null) {
  -            ccs[i++] = (CtConstructor)cc;
  -            cc = cc.next;
  -        }
  +        CtMember.Cache memCache = getMembers();
  +        CtMember cons = memCache.consHead();
  +        CtMember consTail = memCache.lastCons();
   
  -        return ccs;
  -    }
  -
  -    protected CtMember getConstructorsCache() {
  -        if (constructorsCache == null) {
  -            List list = getClassFile2().getMethods();
  -            int n = list.size();
  -            CtMember allConstructors = null;
  -            CtConstructor tail = null;
  -            for (int i = 0; i < n; ++i) {
  -                MethodInfo minfo = (MethodInfo)list.get(i);
  -                if (minfo.isConstructor()) {
  -                    CtConstructor newTail = new CtConstructor(minfo, this);
  -                    allConstructors = CtMember.append(allConstructors, tail, newTail);
  -                    tail = newTail;
  -                }
  +        int n = 0;
  +        CtMember mem = cons;
  +        while (mem != consTail) {
  +            mem = mem.next();
  +            CtConstructor cc = (CtConstructor)mem;
  +            if (cc.isConstructor())
  +                n++;
               }
   
  -            constructorsCache = allConstructors;
  +        CtConstructor[] result = new CtConstructor[n];
  +        int i = 0;
  +        mem = cons;
  +        while (mem != consTail) {
  +            mem = mem.next();
  +            CtConstructor cc = (CtConstructor)mem;
  +            if (cc.isConstructor())
  +                result[i++] = cc;
           }
   
  -        return constructorsCache;
  +        return result;
       }
   
       public CtConstructor getClassInitializer() {
  -        if (classInitializerCache == null) {
  -            MethodInfo minfo = getClassFile2().getStaticInitializer();
  -            if (minfo != null)
  -                classInitializerCache = new CtConstructor(minfo, this);
  +        CtMember.Cache memCache = getMembers();
  +        CtMember cons = memCache.consHead();
  +        CtMember consTail = memCache.lastCons();
  +
  +        while (cons != consTail) {
  +            cons = cons.next();
  +            CtConstructor cc = (CtConstructor)cons;
  +            if (cc.isClassInitializer())
  +                return cc;
           }
   
  -        return classInitializerCache;
  +        return null;
       }
   
       public CtMethod[] getMethods() {
  @@ -940,12 +1035,14 @@
           catch (NotFoundException e) {}
   
           if (cc instanceof CtClassType) {
  -            CtMember cm = ((CtClassType)cc).getMethodsCache();
  -            while (cm != null) {
  -                if (!Modifier.isPrivate(cm.getModifiers()))
  -                    h.put(((CtMethod)cm).getStringRep(), cm);
  -
  -                cm = cm.next;
  +            CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  +            CtMember mth = memCache.methodHead();
  +            CtMember mthTail = memCache.lastMethod();
  +
  +            while (mth != mthTail) {
  +                mth = mth.next();
  +                if (!Modifier.isPrivate(mth.getModifiers()))
  +                    h.put(((CtMethod)mth).getStringRep(), mth);
               }
           }
       }
  @@ -964,13 +1061,15 @@
       private static CtMethod getMethod0(CtClass cc,
                                          String name, String desc) {
           if (cc instanceof CtClassType) {
  -            CtMethod cm = (CtMethod)((CtClassType)cc).getMethodsCache();
  -            while (cm != null) {
  -                if (cm.getName().equals(name)
  -                    && cm.getMethodInfo2().getDescriptor().equals(desc))
  -                    return cm;
  -
  -                cm = (CtMethod)cm.next;
  +            CtMember.Cache memCache = ((CtClassType)cc).getMembers();
  +            CtMember mth = memCache.methodHead();
  +            CtMember mthTail = memCache.lastMethod();
  +
  +            while (mth != mthTail) {
  +                mth = mth.next();
  +                if (mth.getName().equals(name)
  +                        && ((CtMethod)mth).getMethodInfo2().getDescriptor().equals(desc))
  +                    return (CtMethod)mth;
               }
           }
   
  @@ -998,25 +1097,28 @@
       }
   
       public CtMethod[] getDeclaredMethods() {
  -        CtMember cm = getMethodsCache();
  -        int num = CtMember.count(cm);
  +        CtMember.Cache memCache = getMembers();
  +        CtMember mth = memCache.methodHead();
  +        CtMember mthTail = memCache.lastMethod();
  +        int num = CtMember.Cache.count(mth, mthTail);
           CtMethod[] cms = new CtMethod[num];
           int i = 0;
  -        while (cm != null) {
  -            cms[i++] = (CtMethod)cm;
  -            cm = cm.next;
  +        while (mth != mthTail) {
  +            mth = mth.next();
  +            cms[i++] = (CtMethod)mth;
           }
   
           return cms;
       }
   
       public CtMethod getDeclaredMethod(String name) throws NotFoundException {
  -        CtMember m = getMethodsCache();
  -        while (m != null) {
  -            if (m.getName().equals(name))
  -                return (CtMethod)m;
  -
  -            m = m.next;
  +        CtMember.Cache memCache = getMembers();
  +        CtMember mth = memCache.methodHead();
  +        CtMember mthTail = memCache.lastMethod();
  +        while (mth != mthTail) {
  +            mth = mth.next();
  +            if (mth.getName().equals(name))
  +                return (CtMethod)mth;
           }
   
           throw new NotFoundException(name + "(..) is not found in "
  @@ -1027,40 +1129,21 @@
           throws NotFoundException
       {
           String desc = Descriptor.ofParameters(params);
  -        CtMethod m = (CtMethod)getMethodsCache();
  -        while (m != null) {
  -            if (m.getName().equals(name)
  -                && m.getMethodInfo2().getDescriptor().startsWith(desc))
  -                return m;
  -
  -            m = (CtMethod)m.next;
  +        CtMember.Cache memCache = getMembers();
  +        CtMember mth = memCache.methodHead();
  +        CtMember mthTail = memCache.lastMethod();
  +
  +        while (mth != mthTail) {
  +            mth = mth.next();
  +            if (mth.getName().equals(name)
  +                    && ((CtMethod)mth).getMethodInfo2().getDescriptor().startsWith(desc))
  +                return (CtMethod)mth;
           }
   
           throw new NotFoundException(name + "(..) is not found in "
                                       + getName());
       }
   
  -    protected CtMember getMethodsCache() {
  -        if (methodsCache == null) {
  -            List list = getClassFile2().getMethods();
  -            int n = list.size();
  -            CtMember allMethods = null;
  -            CtMethod tail = null;
  -            for (int i = 0; i < n; ++i) {
  -                MethodInfo minfo = (MethodInfo)list.get(i);
  -                if (minfo.isMethod()) {
  -                    CtMethod newTail = new CtMethod(minfo, this);
  -                    allMethods = CtMember.append(allMethods, tail, newTail);
  -                    tail = newTail;
  -                }
  -            }
  -
  -            methodsCache = allMethods;
  -        }
  -
  -        return methodsCache;
  -    }
  -
       public void addField(CtField f, String init)
           throws CannotCompileException
       {
  @@ -1091,8 +1174,7 @@
                   catch (NotFoundException e) {}
           }
   
  -        getFieldsCache();
  -        fieldsCache = CtField.append(fieldsCache, f);
  +        getMembers().addField(f);
           getClassFile2().addField(f.getFieldInfo2());
   
           if (init != null) {
  @@ -1114,7 +1196,7 @@
           FieldInfo fi = f.getFieldInfo2();
           ClassFile cf = getClassFile2();
           if (cf.getFields().remove(fi)) {
  -            fieldsCache = CtMember.remove(fieldsCache, f);
  +            getMembers().remove(f);
               memberRemoved = true;
           }
           else
  @@ -1142,8 +1224,7 @@
           if (c.getDeclaringClass() != this)
               throw new CannotCompileException("cannot add");
   
  -        getConstructorsCache();
  -        constructorsCache = (CtConstructor)CtMember.append(constructorsCache, c);
  +        getMembers().addConstructor(c);
           getClassFile2().addMethod(c.getMethodInfo2());
       }
   
  @@ -1152,7 +1233,7 @@
           MethodInfo mi = m.getMethodInfo2();
           ClassFile cf = getClassFile2();
           if (cf.getMethods().remove(mi)) {
  -            constructorsCache = CtMember.remove(constructorsCache, m);
  +            getMembers().remove(m);
               memberRemoved = true;
           }
           else
  @@ -1164,8 +1245,7 @@
           if (m.getDeclaringClass() != this)
               throw new CannotCompileException("cannot add");
   
  -        getMethodsCache();
  -        methodsCache = CtMember.append(methodsCache, m);
  +        getMembers().addMethod(m);
           getClassFile2().addMethod(m.getMethodInfo2());
           if ((m.getModifiers() & Modifier.ABSTRACT) != 0)
               setModifiers(getModifiers() | Modifier.ABSTRACT);
  @@ -1176,7 +1256,7 @@
           MethodInfo mi = m.getMethodInfo2();
           ClassFile cf = getClassFile2();
           if (cf.getMethods().remove(mi)) {
  -            methodsCache = CtMember.remove(methodsCache, m);
  +            getMembers().remove(m);
               memberRemoved = true;
           }
           else
  @@ -1262,10 +1342,10 @@
               else {
                   classPool.writeClassfile(getName(), out);
                   // to save memory
  -                eraseCache();
  -                classfile = null;
  +                // classfile = null;
               }
   
  +            getCounter = 0;
               wasFrozen = true;
           }
           catch (NotFoundException e) {
  @@ -1328,6 +1408,9 @@
               m.setAccessFlags(AccessFlag.STATIC);
               m.setCodeAttribute(code.toCodeAttribute());
               cf.addMethod(m);
  +            CtMember.Cache cache = hasMemberCache();
  +            if (cache != null)
  +                cache.addConstructor(new CtConstructor(m, this));
           }
           else {
               CodeAttribute codeAttr = m.getCodeAttribute();
  
  
  
  1.11      +3 -0      javassist/src/main/javassist/CtNewWrappedMethod.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtNewWrappedMethod.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtNewWrappedMethod.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -b -r1.10 -r1.11
  --- CtNewWrappedMethod.java	4 Jun 2007 03:11:11 -0000	1.10
  +++ CtNewWrappedMethod.java	8 Jun 2007 13:32:10 -0000	1.11
  @@ -152,6 +152,9 @@
               // a stack map is copied.  rebuilding it is not needed. 
               classfile.addMethod(body);
               bodies.put(src, bodyname);
  +            CtMember.Cache cache = clazz.hasMemberCache();
  +            if (cache != null)
  +                cache.addMethod(new CtMethod(body, clazz));
           }
   
           return bodyname;
  
  
  
  1.22      +0 -2      javassist/src/main/javassist/CtField.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtField.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtField.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -b -r1.21 -r1.22
  --- CtField.java	4 Jun 2007 03:11:11 -0000	1.21
  +++ CtField.java	8 Jun 2007 13:32:10 -0000	1.22
  @@ -97,7 +97,6 @@
           throws CannotCompileException
       {
           super(clazz);
  -        next = null;
           ClassFile cf = clazz.getClassFile2();
           if (cf == null)
               throw new CannotCompileException("bad declaring class: "
  @@ -109,7 +108,6 @@
       CtField(FieldInfo fi, CtClass clazz) {
           super(clazz);
           fieldInfo = fi;
  -        next = null;
       }
   
       /**
  
  
  
  1.18      +97 -41    javassist/src/main/javassist/CtMember.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtMember.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtMember.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -b -r1.17 -r1.18
  --- CtMember.java	4 Jun 2007 03:11:11 -0000	1.17
  +++ CtMember.java	8 Jun 2007 13:32:10 -0000	1.18
  @@ -20,64 +20,120 @@
    * or a method.
    */
   public abstract class CtMember {
  -    protected CtMember next;          // for internal use
  +    CtMember next;          // for internal use
       protected CtClass declaringClass;
   
  -    protected CtMember(CtClass clazz) { declaringClass = clazz; }
  -
  -    static CtMember append(CtMember list, CtMember previousTail, CtMember tail) {
  -        tail.next = null;
  -        if (list == null)
  -            return tail;
  -        else {
  -            previousTail.next = tail;
  -            return list;
  -        }
  +    /* Make a circular link of CtMembers declared in the
  +     * same class so that they are garbage-collected together
  +     * at the same time.
  +     */
  +    static class Cache extends CtMember {
  +        protected void extendToString(StringBuffer buffer) {}
  +        public Object[] getAnnotations()
  +            throws ClassNotFoundException { return null; }
  +        public byte[] getAttribute(String name) { return null; }
  +        public Object[] getAvailableAnnotations()
  +            throws ClassNotFoundException { return null; }
  +        public int getModifiers() { return 0; }
  +        public String getName() { return null; }
  +        public String getSignature() { return null; }
  +        public void setAttribute(String name, byte[] data) {}
  +        public void setModifiers(int mod) {}
  +
  +        private CtMember methodTail;
  +        private CtMember consTail;     // constructor tail
  +        private CtMember fieldTail;
  +
  +        Cache(CtClassType decl) {
  +            super(decl);
  +            methodTail = this;
  +            consTail = this;
  +            fieldTail = this;
  +            fieldTail.next = this;
  +        }
  +
  +        CtMember methodHead() { return this; }
  +        CtMember lastMethod() { return methodTail; }
  +        CtMember consHead() { return methodTail; }      // may include a static initializer
  +        CtMember lastCons() { return consTail; }
  +        CtMember fieldHead() { return consTail; }
  +        CtMember lastField() { return fieldTail; }
  +
  +        void addMethod(CtMember method) {
  +            method.next = methodTail.next;
  +            methodTail.next = method;
  +            if (methodTail == consTail) {
  +                consTail = method;
  +                if (methodTail == fieldTail)
  +                    fieldTail = method;
  +            }
  +
  +            methodTail = method;
  +        }
  +
  +        /* Both constructors and a class initializer.
  +         */
  +        void addConstructor(CtMember cons) {
  +            cons.next = consTail.next;
  +            consTail.next = cons;
  +            if (consTail == fieldTail)
  +                fieldTail = cons;
  +
  +            consTail = cons;
  +        }
  +
  +        void addField(CtMember field) {
  +            field.next = this; // or fieldTail.next
  +            fieldTail.next = field;
  +            fieldTail = field;
       }
   
  -    static CtMember append(CtMember list, CtMember tail) {
  -        tail.next = null;
  -        if (list == null)
  -            return tail;
  -        else {
  -            CtMember lst = list;
  -            while (lst.next != null)
  -                lst = lst.next;
  -
  -            lst.next = tail;
  -            return list;
  -        }
  -    }
  -
  -    static int count(CtMember f) {
  +        static int count(CtMember head, CtMember tail) {
           int n = 0;
  -        while (f != null) {
  -            ++n;
  -            f = f.next;
  +            while (head != tail) {
  +                n++;
  +                head = head.next;
           }
   
           return n;
       }
   
  -    static CtMember remove(CtMember list, CtMember m) {
  -        CtMember top = list;
  -        if (list == null)
  -            return null;
  -        else if (list == m)
  -            return list.next;
  -        else
  -            while (list.next != null) {
  -                if (list.next == m) {
  -                    list.next = list.next.next;
  +        void remove(CtMember mem) {
  +            CtMember m = this;
  +            CtMember node;
  +            while ((node = m.next) != this) {
  +                if (node == mem) {
  +                    m.next = node.next;
  +                    if (node == methodTail)
  +                        methodTail = m;
  +                    else if (node == consTail)
  +                        consTail = m;
  +                    else if (node == fieldTail)
  +                        fieldTail = m;
  +
                       break;
                   }
  -
  -                list = list.next;
  +                else
  +                    m = m.next;
  +            }
  +        }
               }
   
  -        return top;
  +    protected CtMember(CtClass clazz) {
  +        declaringClass = clazz;
  +        next = null;
       }
   
  +    final CtMember next() { return next; }
  +
  +    /**
  +     * This method is invoked when setName() or replaceClassName()
  +     * in CtClass is called.
  +     *
  +     * @see CtMethod#nameReplaced()
  +     */
  +    void nameReplaced() {}
  +
       public String toString() {
           StringBuffer buffer = new StringBuffer(getClass().getName());
           buffer.append("@");
  
  
  
  1.85      +13 -5     javassist/src/main/javassist/CtClass.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtClass.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtClass.java,v
  retrieving revision 1.84
  retrieving revision 1.85
  diff -u -b -r1.84 -r1.85
  --- CtClass.java	4 Jun 2007 03:11:11 -0000	1.84
  +++ CtClass.java	8 Jun 2007 13:32:10 -0000	1.85
  @@ -52,7 +52,7 @@
       /**
        * The version number of this release.
        */
  -    public static final String version = "3.6.0BETA";
  +    public static final String version = "3.6.0beta2";
   
       /**
        * Prints the version number and the copyright notice.
  @@ -1126,7 +1126,8 @@
        * save memory consumption.
        *
        * <p>If <code>ClassPool.doPruning</code> is true, the automatic pruning
  -     * is on by default.  Otherwise, it is off.
  +     * is on by default.  Otherwise, it is off.  The default value of
  +     * <code>ClassPool.doPruning</code> is false.
        * 
        * @param stop      disallow pruning if true.  Otherwise, allow.
        * @return the previous status of pruning.  true if pruning is already stopped.
  @@ -1150,15 +1151,22 @@
        * are still accessible.
        *
        * <p><code>toBytecode()</code>, <code>writeFile()</code>, and
  -     * <code>toClass()</code> internally call this method. 
  +     * <code>toClass()</code> internally call this method if
  +     * automatic pruning is on. 
  +     *
  +     * <p>According to some experiments, pruning does not really reduce
  +     * memory consumption.  Only about 20%.  Since pruning takes time,
  +     * it might not pay off.  So the automatic pruning is off by default.
  +     *
  +     * @see #stopPruning(boolean)
  +     * @see #detach()
  +     * @see ClassPool#doPruning
        *
        * @see #toBytecode()
        * @see #toClass()
        * @see #writeFile()
        * @see #instrument(CodeConverter)
        * @see #instrument(ExprEditor)
  -     *
  -     * @see #stopPruning(boolean)
        */
       public void prune() {}
   
  
  
  
  1.63      +3 -2      javassist/src/main/javassist/ClassPool.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ClassPool.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/ClassPool.java,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -b -r1.62 -r1.63
  --- ClassPool.java	4 Jun 2007 03:11:11 -0000	1.62
  +++ ClassPool.java	8 Jun 2007 13:32:10 -0000	1.63
  @@ -111,12 +111,13 @@
        * are called.  The automatic pruning can be turned on/off individually
        * for each <code>CtClass</code> object.
        *
  -     * <p>The initial value is true.
  +     * <p>The initial value is false.
        *
        * @see CtClass#prune()
        * @see CtClass#stopPruning(boolean)
  +     * @see CtClass#detach()
        */
  -    public static boolean doPruning = true;
  +    public static boolean doPruning = false;
   
       /* releaseUnmodifiedClassFile was introduced for avoiding a bug
          of JBoss AOP.  So the value should be true except for JBoss AOP.
  
  
  
  1.18      +8 -1      javassist/src/main/javassist/CtMethod.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtMethod.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtMethod.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -b -r1.17 -r1.18
  --- CtMethod.java	4 Jun 2007 03:11:11 -0000	1.17
  +++ CtMethod.java	8 Jun 2007 13:32:10 -0000	1.18
  @@ -32,7 +32,6 @@
   
       CtMethod(MethodInfo minfo, CtClass declaring) {
           super(declaring, minfo);
  -        next = null;
           cachedStringRep = null;
       }
   
  @@ -135,6 +134,14 @@
           return getStringRep().hashCode();
       }
   
  +    /**
  +     * This method is invoked when setName() or replaceClassName()
  +     * in CtClass is called.
  +     */
  +    void nameReplaced() {
  +        cachedStringRep = null;
  +    }
  +
       /* This method is also called by CtClassType.getMethods0(). 
        */
       final String getStringRep() {
  
  
  
  1.21      +0 -1      javassist/src/main/javassist/CtConstructor.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: CtConstructor.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/CtConstructor.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -b -r1.20 -r1.21
  --- CtConstructor.java	4 Jun 2007 03:11:11 -0000	1.20
  +++ CtConstructor.java	8 Jun 2007 13:32:10 -0000	1.21
  @@ -35,7 +35,6 @@
   public final class CtConstructor extends CtBehavior {
       protected CtConstructor(MethodInfo minfo, CtClass declaring) {
           super(declaring, minfo);
  -        next = null;
       }
   
       /**
  
  
  



More information about the jboss-cvs-commits mailing list