]> source.dussan.org Git - javassist.git/commitdiff
Fix pruning so that exceptions and annotation attributes are not ditched.
authorbill <bill@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 9 Jun 2005 04:15:31 +0000 (04:15 +0000)
committerbill <bill@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>
Thu, 9 Jun 2005 04:15:31 +0000 (04:15 +0000)
Add more hooks for jBoss AOP so that it can prune aggressively.

git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@178 30ef5769-5b8d-40dd-aea6-55b5d6557bb3

src/main/META-INF/MANIFEST.MF
src/main/javassist/ClassPool.java
src/main/javassist/CtClass.java
src/main/javassist/CtClassType.java
src/main/javassist/bytecode/ClassFile.java
src/main/javassist/bytecode/FieldInfo.java
src/main/javassist/bytecode/MethodInfo.java

index efb842106937b80563b705991fafdc69a49f5661..06bf32f4114f659315767c6ab20b32a8a705aa5a 100644 (file)
@@ -2,7 +2,7 @@ Manifest-Version: 1.1
 Specification-Title: Javassist
 Created-By: Shigeru Chiba, Tokyo Institute of Technology
 Specification-Vendor: Shigeru Chiba, Tokyo Institute of Technology
-Specification-Version: 3.0
+Specification-Version: 3.1RC1
 Main-Class: javassist.CtClass
 
 Name: javassist/
index bf1c73ac989287e6ac591c1bf3ef746d57d805c9..05b0bb82bea625a0e527e520797ce6f096dab844 100644 (file)
@@ -150,7 +150,7 @@ public class ClassPool {
      * Provide a hook so that subclasses can do their own
      * caching of classes.
      *
-     * @see #cacheCtClass(String,CtClass)
+     * @see #cacheCtClass(String,CtClass,boolean)
      * @see #removeCached(String)
      */
     protected CtClass getCached(String classname) {
@@ -164,7 +164,7 @@ public class ClassPool {
      * @see #getCached(String)
      * @see #removeCached(String,CtClass)
      */
-    protected void cacheCtClass(String classname, CtClass c) {
+    protected void cacheCtClass(String classname, CtClass c, boolean dynamic) {
         classes.put(classname, c);
     }
 
@@ -173,7 +173,7 @@ public class ClassPool {
      * caching of classes.
      *
      * @see #getCached(String)
-     * @see #cacheCtClass(String,CtClass)
+     * @see #cacheCtClass(String,CtClass,boolean)
      */
     protected CtClass removeCached(String classname) {
         return (CtClass)classes.remove(classname);
@@ -272,7 +272,7 @@ public class ClassPool {
 
         String newName = clazz.getName();
         checkNotFrozen(newName);
-        cacheCtClass(newName, clazz);
+        cacheCtClass(newName, clazz, false);
     }
 
     /**
@@ -330,7 +330,7 @@ public class ClassPool {
         clazz = createCtClass(classname, useCache);
         if (clazz != null) {
             if (useCache)
-                cacheCtClass(classname, clazz);
+                cacheCtClass(classname, clazz, false);
 
             return clazz;
         }
@@ -475,7 +475,7 @@ public class ClassPool {
         clazz.checkModify();
         String classname = clazz.getName();
         checkNotFrozen(classname);
-        cacheCtClass(classname, clazz);
+        cacheCtClass(classname, clazz, true);
         return clazz;
     }
 
@@ -505,7 +505,7 @@ public class ClassPool {
     {
         checkNotFrozen(classname);
         CtClass clazz = new CtNewClass(classname, this, false, superclass);
-        cacheCtClass(classname, clazz);
+        cacheCtClass(classname, clazz, true);
         return clazz;
     }
 
@@ -519,7 +519,7 @@ public class ClassPool {
     synchronized CtClass makeNestedClass(String classname) {
         checkNotFrozen(classname);
         CtClass clazz = new CtNewNestedClass(classname, this, false, null);
-        cacheCtClass(classname, clazz);
+        cacheCtClass(classname, clazz, true);
         return clazz;
     }
 
@@ -549,7 +549,7 @@ public class ClassPool {
     {
         checkNotFrozen(name);
         CtClass clazz = new CtNewClass(name, this, true, superclass);
-        cacheCtClass(name, clazz);
+        cacheCtClass(name, clazz, true);
         return clazz;
     }
 
index 2acd57764d03cc5151fe3b1cf6c9518459d8851b..91123108352308b8727727a348f19a9c8a0cfaa0 100644 (file)
 
 package javassist;
 
-import javassist.bytecode.ClassFile;
-import javassist.bytecode.Descriptor;
-import javassist.bytecode.Opcode;
-import javassist.expr.ExprEditor;
-
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
@@ -29,6 +24,10 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
 import java.util.Collection;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.Descriptor;
+import javassist.bytecode.Opcode;
+import javassist.expr.ExprEditor;
 
 // Subclasses of CtClass: CtClassType, CtPrimitiveType, and CtArray
 
@@ -1004,7 +1003,7 @@ public abstract class CtClass {
         ClassPool cp = getClassPool();
         CtClass obj = cp.removeCached(getName());
         if (obj != this)
-            cp.cacheCtClass(getName(), obj);
+            cp.cacheCtClass(getName(), obj, false);
     }
 
     /**
@@ -1112,6 +1111,11 @@ public abstract class CtClass {
         }
     }
 
+   public void prune()
+   {
+
+   }
+
     /**
      * Converts this class to a class file.
      * Once this method is called, further modifications are not
index 4fd3ff90a933c4ce3c10a6bd743b188208567273..17dfab27e51afcad89db00ae8fabad5f49c4236d 100644 (file)
 
 package javassist;
 
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
 import javassist.bytecode.AccessFlag;
 import javassist.bytecode.AttributeInfo;
 import javassist.bytecode.BadBytecode;
@@ -33,18 +44,6 @@ import javassist.compiler.CompileError;
 import javassist.compiler.Javac;
 import javassist.expr.ExprEditor;
 
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-
 /**
  * Class types.
  */
@@ -174,10 +173,13 @@ class CtClassType extends CtClass {
         if (classfile != null)
             return classfile;
 
+       /*
         if (readCounter++ > READ_THRESHOLD) {
+            System.out.println("COMPACTING!!!!: " + getName());
             doCompaction();
             readCounter = 0;
         }
+        */
 
         InputStream fin = null;
         try {
@@ -962,6 +964,13 @@ class CtClassType extends CtClass {
         }
     }
 
+   public void prune()
+   {
+      if (wasPruned) return;
+      wasPruned = true;
+      getClassFile2().prune();
+   }
+
     public void toBytecode(DataOutputStream out)
         throws CannotCompileException, IOException
     {
@@ -981,7 +990,7 @@ class CtClassType extends CtClass {
                 fieldInitializers = null;
                 if (doPruning) {
                     // to save memory
-                    cf.prune();
+                    cf. prune();
                     wasPruned = true;
                 }
             }
index ddcd5d8df4c25cefa4314e3741cc8a4b4659ccd5..77ba885b132254f524aeaf4a04752a1f92c26cbd 100644 (file)
@@ -18,12 +18,11 @@ package javassist.bytecode;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.util.Map;
-import java.util.LinkedList;
 import java.util.ArrayList;
-import java.util.ListIterator;
+import java.util.LinkedList;
 import java.util.List;
-
+import java.util.ListIterator;
+import java.util.Map;
 import javassist.CannotCompileException;
 
 /**
@@ -32,631 +31,726 @@ import javassist.CannotCompileException;
  *
  * @see javassist.CtClass#getClassFile()
  */
-public final class ClassFile {
-    int major, minor;           // version number
-    ConstPool constPool;
-    int thisClass;
-    int accessFlags;
-    int superClass;
-    int[] interfaces;
-    ArrayList fields;
-    ArrayList methods;
-    LinkedList attributes;
-
-    String thisclassname;       // not JVM-internal name
-
-    /**
-     * Constructs a class file from a byte stream.
-     */
-    public ClassFile(DataInputStream in) throws IOException {
-        read(in);
-    }
-
-    /**
-     * Constructs a class file including no members.
-     *
-     * @param isInterface       true if this is an interface.
-     *                          false if this is a class.
-     * @param classname         a fully-qualified class name
-     * @param superclass        a fully-qualified super class name
-     */
-    public ClassFile(boolean isInterface,
-                     String classname, String superclass) {
-        major = 45;
-        minor = 3;      // JDK 1.1 or later
-        constPool = new ConstPool(classname);
-        thisClass = constPool.getThisClassInfo();
-        if (isInterface)
-            accessFlags = AccessFlag.SUPER | AccessFlag.INTERFACE
-                | AccessFlag.ABSTRACT;
-        else
-            accessFlags = AccessFlag.SUPER;
-
-        initSuperclass(superclass);
-        interfaces = null;
-        fields = new ArrayList();
-        methods = new ArrayList();
-        thisclassname = classname;
-
-        attributes = new LinkedList();
-        attributes.add(new SourceFileAttribute(constPool,
-                                        getSourcefileName(thisclassname)));
-    }
-
-    private void initSuperclass(String superclass) {
-        if (superclass != null)
-            superClass = constPool.addClassInfo(superclass);
-        else
-            superClass = constPool.addClassInfo("java.lang.Object");
-    }
-
-    private static String getSourcefileName(String qname) {
-        int index = qname.lastIndexOf('.');
-        if (index >= 0)
-            qname = qname.substring(index + 1);
-
-        return qname + ".java";
-    }
-
-    /**
-     * Eliminates dead constant pool items.  If a method or a field is removed,
-     * the constant pool items used by that method/field become dead items.
-     * This method recreates a constant pool.
-     */
-    public void compact() {
-        ConstPool cp = compact0();
-        ArrayList list = methods;
-        int n = list.size();
-        for (int i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            minfo.compact(cp);
-        }
-
-        list = fields;
-        n = list.size();
-        for (int i = 0; i < n; ++i) {
-            FieldInfo finfo = (FieldInfo)list.get(i);
-            finfo.compact(cp);
-        }
-
-        attributes = AttributeInfo.copyAll(attributes, cp);
-        constPool = cp;
-    }
-
-    private ConstPool compact0() {
-        ConstPool cp = new ConstPool(thisclassname);
-        thisClass = cp.getThisClassInfo();
-        superClass = cp.addClassInfo(getSuperclass());
-
-        if (interfaces != null) {
-            int n = interfaces.length;
-            for (int i = 0; i < n; ++i)
-                interfaces[i]
-                    = cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
-        }
-
-        return cp;
-    }
-
-    /**
-     * Discards all attributes, associated with both the class file and
-     * the members such as a code attribute and exceptions attribute.
-     * The unused constant pool entries are also discarded (a new packed
-     * constant pool is constructed).
-     */
-    public void prune() {
-        ConstPool cp = compact0();
-
-        ArrayList list = methods;
-        int n = list.size();
-        for (int i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            minfo.prune(cp);
-        }
-
-        list = fields;
-        n = list.size();
-        for (int i = 0; i < n; ++i) {
-            FieldInfo finfo = (FieldInfo)list.get(i);
-            finfo.prune(cp);
-        }
-
-        attributes = new LinkedList();
-        cp.prune();
-        constPool = cp;
-    }
-
-    /**
-     * Returns a constant pool table.
-     */
-    public ConstPool getConstPool() {
-        return constPool;
-    }
-
-    /**
-     * Returns true if this is an interface.
-     */
-    public boolean isInterface() {
-        return (accessFlags & AccessFlag.INTERFACE) != 0;
-    }
-
-    /**
-     * Returns true if this is a final class or interface.
-     */
-    public boolean isFinal() {
-        return (accessFlags & AccessFlag.FINAL) != 0;
-    }
-
-    /**
-     * Returns true if this is an abstract class or an interface.
-     */
-    public boolean isAbstract() {
-        return (accessFlags & AccessFlag.ABSTRACT) != 0;
-    }
-
-    /**
-     * Returns access flags.
-     *
-     * @see javassist.bytecode.AccessFlag
-     */
-    public int getAccessFlags() {
-        return accessFlags;
-    }
-
-    /**
-     * Changes access flags.
-     *
-     * @see javassist.bytecode.AccessFlag
-     */
-    public void setAccessFlags(int acc) {
-        accessFlags = acc | AccessFlag.SUPER;
-    }
-
-    /**
-     * Returns the class name.
-     */
-    public String getName() {
-        return thisclassname;
-    }
-
-    /**
-     * Sets the class name.  This method substitutes the new name
-     * for all occurrences of the old class name in the class file.
-     */
-    public void setName(String name) {
-        renameClass(thisclassname, name);
-    }
-
-    /**
-     * Returns the super class name.
-     */
-    public String getSuperclass() {
-        return constPool.getClassInfo(superClass);
-    }
-
-    /**
-     * Returns the index of the constant pool entry representing
-     * the super class.
-     */
-    public int getSuperclassId() {
-        return superClass;
-    }
-
-    /**
-     * Sets the super class.
-     *
-     * <p>This method modifies constructors so that they call
-     * constructors declared in the new super class.
-     */
-    public void setSuperclass(String superclass)
-        throws CannotCompileException
-    {
-        if (superclass == null)
-            superclass = "java.lang.Object";
-
-        try {
-            superClass = constPool.addClassInfo(superclass);
-            ArrayList list = methods;
-            int n = list.size();
-            for (int i = 0; i < n; ++i) {
-                MethodInfo minfo = (MethodInfo)list.get(i);
-                minfo.setSuperclass(superclass);
-            }
-        }
-        catch (BadBytecode e) {
-            throw new CannotCompileException(e);
-        }
-    }
-
-    /**
-     * Replaces all occurrences of a class name in the class file.
-     *
-     * <p>If class X is substituted for class Y in the class file,
-     * X and Y must have the same signature.  If Y provides a method
-     * m(), X must provide it even if X inherits m() from the super class.
-     * If this fact is not guaranteed, the bytecode verifier may cause
-     * an error.
-     *
-     * @param oldname           the replaced class name
-     * @param newname           the substituted class name
-     */
-    public final void renameClass(String oldname, String newname) {
-        ArrayList list;
-        int n;
-
-        if (oldname.equals(newname))
-            return;
-
-        if (oldname.equals(thisclassname))
-            thisclassname = newname;
-
-        oldname = Descriptor.toJvmName(oldname);
-        newname = Descriptor.toJvmName(newname);
-        constPool.renameClass(oldname, newname);
-
-        list = methods;
-        n = list.size();
-        for (int i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            String desc = minfo.getDescriptor();
-            minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
-        }
-
-        list = fields;
-        n = list.size();
-        for (int i = 0; i < n; ++i) {
-            FieldInfo finfo = (FieldInfo)list.get(i);
-            String desc = finfo.getDescriptor();
-            finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
-        }
-    }
-
-    /**
-     * Replaces all occurrences of several class names in the class file.
-     *
-     * @param classnames        specifies which class name is replaced
-     *                          with which new name.  Class names must
-     *                          be described with the JVM-internal
-     *                          representation like
-     *                          <code>java/lang/Object</code>.
-     *
-     * @see #renameClass(String,String)
-     */
-    public final void renameClass(Map classnames) {
-        String jvmNewThisName
-            = (String)classnames.get(Descriptor.toJvmName(thisclassname));
-        if (jvmNewThisName != null)
-            thisclassname = Descriptor.toJavaName(jvmNewThisName);
-
-        constPool.renameClass(classnames);
-
-        ArrayList list = methods;
-        int n = list.size();
-        for (int i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            String desc = minfo.getDescriptor();
-            minfo.setDescriptor(Descriptor.rename(desc, classnames));
-        }
-
-        list = fields;
-        n = list.size();
-        for (int i = 0; i < n; ++i) {
-            FieldInfo finfo = (FieldInfo)list.get(i);
-            String desc = finfo.getDescriptor();
-            finfo.setDescriptor(Descriptor.rename(desc, classnames));
-        }
-    }
-
-    /**
-     * Returns the names of the interfaces implemented by the class.
-     */
-    public String[] getInterfaces() {
-        if (interfaces == null)
-            return new String[0];
-        else {
-            int n = interfaces.length;
-            String[] list = new String[n];
-            for (int i = 0; i < n; ++i)
-                list[i] = constPool.getClassInfo(interfaces[i]);
-
-            return list;
-        }
-    }
-
-    /**
-     * Sets the interfaces.
-     *
-     * @param nameList          the names of the interfaces.
-     */
-    public void setInterfaces(String[] nameList) {
-        if (nameList != null) {
-            int n = nameList.length;
-            interfaces = new int[n];
-            for (int i = 0; i < n; ++i)
-                interfaces[i] = constPool.addClassInfo(nameList[i]);
-        }
-    }
-
-    /**
-     * Appends an interface to the
-     * interfaces implemented by the class.
-     */
-    public void addInterface(String name) {
-        int info = constPool.addClassInfo(name);
-        if (interfaces == null) {
-            interfaces = new int[1];
-            interfaces[0] = info;
-        }
-        else {
-            int n = interfaces.length;
-            int[] newarray = new int[n + 1];
-            System.arraycopy(interfaces, 0, newarray, 0, n);
-            newarray[n] = info;
-            interfaces = newarray;
-        }
-    }
-
-    /**
-     * Returns all the fields declared in the class.
-     *
-     * @return a list of <code>FieldInfo</code>.
-     * @see FieldInfo
-     */
-    public List getFields() {
-        return fields;
-    }
-
-    /**
-     * Appends a field to the class.
-     */
-    public void addField(FieldInfo finfo) throws CannotCompileException {
-        testExistingField(finfo.getName(), finfo.getDescriptor());
-        fields.add(finfo);
-    }
-
-    private void addField0(FieldInfo finfo) {
-        fields.add(finfo);
-    }
-
-    private void testExistingField(String name, String descriptor)
-        throws CannotCompileException
-    {
-        ListIterator it = fields.listIterator(0);
-        while (it.hasNext()) {
-            FieldInfo minfo = (FieldInfo)it.next();
-            if (minfo.getName().equals(name))
-                throw new CannotCompileException("duplicate field: " + name);
-        }
-    }
-
-    /**
-     * Returns all the methods declared in the class.
-     *
-     * @return a list of <code>MethodInfo</code>.
-     * @see MethodInfo
-     */
-    public List getMethods() {
-        return methods;
-    }
-
-    /**
-     * Returns the method with the specified name.  If there are multiple
-     * methods with that name, this method returns one of them.
-     *
-     * @return null             if no such a method is found.
-     */
-    public MethodInfo getMethod(String name) {
-        ArrayList list = methods;
-        int n = list.size();
-        for (int i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            if (minfo.getName().equals(name))
-                return minfo;
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns a static initializer (class initializer), or null if
-     * it does not exist.
-     */
-    public MethodInfo getStaticInitializer() {
-        return getMethod(MethodInfo.nameClinit);
-    }
-
-    /**
-     * Appends a method to the class.
-     */
-    public void addMethod(MethodInfo minfo) throws CannotCompileException {
-        testExistingMethod(minfo.getName(), minfo.getDescriptor());
-        methods.add(minfo);
-    }
-
-    private void addMethod0(MethodInfo minfo) {
-        methods.add(minfo);
-    }
-
-    private void testExistingMethod(String name, String descriptor)
-        throws CannotCompileException
-    {
-        ListIterator it = methods.listIterator(0);
-        while (it.hasNext()) {
-            MethodInfo minfo = (MethodInfo)it.next();
-            if (minfo.getName().equals(name)
-                && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor))
-                throw new CannotCompileException("duplicate method: " + name);
-        }
-    }
-
-    /**
-     * Returns all the attributes.
-     *
-     * @return a list of <code>AttributeInfo</code> objects.
-     * @see AttributeInfo
-     */
-    public List getAttributes() {
-        return attributes;
-    }
-
-    /**
-     * Returns the attribute with the specified name.
-     *
-     * @param name      attribute name
-     */
-    public AttributeInfo getAttribute(String name) {
-        LinkedList list = attributes;
-        int n = list.size();
-        for (int i = 0; i < n; ++i) {
-            AttributeInfo ai = (AttributeInfo)list.get(i);
-            if (ai.getName().equals(name))
-                return ai;
-        }
-
-        return null;
-    }
-
-    /**
-     * Appends an attribute.  If there is already an attribute with
-     * the same name, the new one substitutes for it.
-     */
-    public void addAttribute(AttributeInfo info) {
-        AttributeInfo.remove(attributes, info.getName());
-        attributes.add(info);
-    }
-
-    /**
-     * Returns the source file containing this class.
-     *
-     * @return null     if this information is not available.
-     */
-    public String getSourceFile() {
-        SourceFileAttribute sf
-            = (SourceFileAttribute)getAttribute(SourceFileAttribute.tag);
-        if (sf == null)
-            return null;
-        else
-            return sf.getFileName();
-    }
-
-    private void read(DataInputStream in) throws IOException {
-        int i, n;
-        int magic = in.readInt();
-        if (magic != 0xCAFEBABE)
-            throw new IOException("non class file");
-
-        minor = in.readUnsignedShort();
-        major = in.readUnsignedShort();
-        constPool = new ConstPool(in);
-        accessFlags = in.readUnsignedShort();
-        thisClass = in.readUnsignedShort();
-        constPool.setThisClassInfo(thisClass);
-        superClass = in.readUnsignedShort();
-        n = in.readUnsignedShort();
-        if (n == 0)
-            interfaces = null;
-        else {
-            interfaces = new int[n];
-            for (i = 0; i < n; ++i)
-                interfaces[i] = in.readUnsignedShort();
-        }
-
-        ConstPool cp = constPool;
-        n = in.readUnsignedShort();
-        fields = new ArrayList();
-        for (i = 0; i < n; ++i)
-            addField0(new FieldInfo(cp, in));
-
-        n = in.readUnsignedShort();
-        methods = new ArrayList();
-        for (i = 0; i < n; ++i)
-            addMethod0(new MethodInfo(cp, in));
-
-        attributes = new LinkedList();
-        n = in.readUnsignedShort();
-        for (i = 0; i < n; ++i)
-            addAttribute(AttributeInfo.read(cp, in));
-
-        thisclassname = constPool.getClassInfo(thisClass);
-    }
-
-    /**
-     * Writes a class file represened by this object
-     * into an output stream.
-     */
-    public void write(DataOutputStream out) throws IOException {
-        int i, n;
-
-        out.writeInt(0xCAFEBABE);       // magic
-        out.writeShort(minor);          // minor version
-        out.writeShort(major);          // major version
-        constPool.write(out);           // constant pool
-        out.writeShort(accessFlags);
-        out.writeShort(thisClass);
-        out.writeShort(superClass);
-
-        if (interfaces == null)
-            n = 0;
-        else
-            n = interfaces.length;
-
-        out.writeShort(n);
-        for (i = 0; i < n; ++i)
-            out.writeShort(interfaces[i]);
-
-        ArrayList list = fields;
-        n = list.size();
-        out.writeShort(n);
-        for (i = 0; i < n; ++i) {
-            FieldInfo finfo = (FieldInfo)list.get(i);
-            finfo.write(out);
-        }
-
-        list = methods;
-        n = list.size();
-        out.writeShort(n);
-        for (i = 0; i < n; ++i) {
-            MethodInfo minfo = (MethodInfo)list.get(i);
-            minfo.write(out);
-        }
-
-        out.writeShort(attributes.size());
-        AttributeInfo.writeAll(attributes, out);
-    }
-
-    /**
-     * Get the Major version.
-     *
-     * @return the major version
-     */
-    public int getMajorVersion() {
-        return major;
-    }
-
-    /**
-     * Set the Major version.
-     *
-     * @param major         the major version
-     */
-    public void setMajorVersion(int major) {
-       this.major = major;
-    }
-
-    /**
-     * Get the Minor version.
-     *
-     * @return the minor version
-     */
-    public int getMinorVersion() {
-        return minor;
-    }
-
-    /**
-     * Set the Minor version.
-     *
-     * @param minor         the minor version
-     */
-    public void setMinorVersion(int minor) {
-       this.minor = minor;
-    }
+public final class ClassFile
+{
+   int major, minor;           // version number
+   ConstPool constPool;
+   int thisClass;
+   int accessFlags;
+   int superClass;
+   int[] interfaces;
+   ArrayList fields;
+   ArrayList methods;
+   LinkedList attributes;
+
+   String thisclassname;       // not JVM-internal name
+   String[] cachedInterfaces;
+   String cachedSuperclass;
+
+   /**
+    * Constructs a class file from a byte stream.
+    */
+   public ClassFile(DataInputStream in) throws IOException
+   {
+      read(in);
+   }
+
+   /**
+    * Constructs a class file including no members.
+    *
+    * @param isInterface true if this is an interface.
+    *                    false if this is a class.
+    * @param classname   a fully-qualified class name
+    * @param superclass  a fully-qualified super class name
+    */
+   public ClassFile(boolean isInterface,
+                    String classname, String superclass)
+   {
+      major = 45;
+      minor = 3;      // JDK 1.1 or later
+      constPool = new ConstPool(classname);
+      thisClass = constPool.getThisClassInfo();
+      if (isInterface)
+         accessFlags = AccessFlag.SUPER | AccessFlag.INTERFACE
+                       | AccessFlag.ABSTRACT;
+      else
+         accessFlags = AccessFlag.SUPER;
+
+      initSuperclass(superclass);
+      interfaces = null;
+      fields = new ArrayList();
+      methods = new ArrayList();
+      thisclassname = classname;
+
+      attributes = new LinkedList();
+      attributes.add(new SourceFileAttribute(constPool,
+                                             getSourcefileName(thisclassname)));
+   }
+
+   private void initSuperclass(String superclass)
+   {
+      if (superclass != null)
+      {
+         this.superClass = constPool.addClassInfo(superclass);
+         cachedSuperclass = superclass;
+      }
+      else
+      {
+         this.superClass = constPool.addClassInfo("java.lang.Object");
+         cachedSuperclass = "java.lang.Object";
+      }
+   }
+
+   private static String getSourcefileName(String qname)
+   {
+      int index = qname.lastIndexOf('.');
+      if (index >= 0)
+         qname = qname.substring(index + 1);
+
+      return qname + ".java";
+   }
+
+   /**
+    * Eliminates dead constant pool items.  If a method or a field is removed,
+    * the constant pool items used by that method/field become dead items.
+    * This method recreates a constant pool.
+    */
+   public void compact()
+   {
+      ConstPool cp = compact0();
+      ArrayList list = methods;
+      int n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         minfo.compact(cp);
+      }
+
+      list = fields;
+      n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         FieldInfo finfo = (FieldInfo) list.get(i);
+         finfo.compact(cp);
+      }
+
+      attributes = AttributeInfo.copyAll(attributes, cp);
+      constPool = cp;
+   }
+
+   private ConstPool compact0()
+   {
+      ConstPool cp = new ConstPool(thisclassname);
+      thisClass = cp.getThisClassInfo();
+      String sc = getSuperclass();
+      if (sc != null)
+      {
+         superClass = cp.addClassInfo(getSuperclass());
+      }
+
+      if (interfaces != null)
+      {
+         int n = interfaces.length;
+         for (int i = 0; i < n; ++i)
+            interfaces[i]
+            = cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
+      }
+
+      return cp;
+   }
+
+   /**
+    * Discards all attributes, associated with both the class file and
+    * the members such as a code attribute and exceptions attribute.
+    * The unused constant pool entries are also discarded (a new packed
+    * constant pool is constructed).
+    */
+   public void prune()
+   {
+      ConstPool cp = compact0();
+      AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
+      LinkedList newAttributes = new LinkedList();
+      if (invisibleAnnotations != null)
+      {
+         invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+         newAttributes.add(invisibleAnnotations);
+      }
+      AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
+      if (visibleAnnotations != null)
+      {
+         visibleAnnotations = visibleAnnotations.copy(cp, null);
+         newAttributes.add(visibleAnnotations);
+      }
+
+      ArrayList list = methods;
+      int n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         minfo.prune(cp);
+      }
+
+      list = fields;
+      n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         FieldInfo finfo = (FieldInfo) list.get(i);
+         finfo.prune(cp);
+      }
+      attributes = newAttributes;
+      cp.prune();
+      constPool = cp;
+   }
+
+   /**
+    * Returns a constant pool table.
+    */
+   public ConstPool getConstPool()
+   {
+      return constPool;
+   }
+
+   /**
+    * Returns true if this is an interface.
+    */
+   public boolean isInterface()
+   {
+      return (accessFlags & AccessFlag.INTERFACE) != 0;
+   }
+
+   /**
+    * Returns true if this is a final class or interface.
+    */
+   public boolean isFinal()
+   {
+      return (accessFlags & AccessFlag.FINAL) != 0;
+   }
+
+   /**
+    * Returns true if this is an abstract class or an interface.
+    */
+   public boolean isAbstract()
+   {
+      return (accessFlags & AccessFlag.ABSTRACT) != 0;
+   }
+
+   /**
+    * Returns access flags.
+    *
+    * @see javassist.bytecode.AccessFlag
+    */
+   public int getAccessFlags()
+   {
+      return accessFlags;
+   }
+
+   /**
+    * Changes access flags.
+    *
+    * @see javassist.bytecode.AccessFlag
+    */
+   public void setAccessFlags(int acc)
+   {
+      accessFlags = acc | AccessFlag.SUPER;
+   }
+
+   /**
+    * Returns the class name.
+    */
+   public String getName()
+   {
+      return thisclassname;
+   }
+
+   /**
+    * Sets the class name.  This method substitutes the new name
+    * for all occurrences of the old class name in the class file.
+    */
+   public void setName(String name)
+   {
+      renameClass(thisclassname, name);
+   }
+
+   /**
+    * Returns the super class name.
+    */
+   public String getSuperclass()
+   {
+      if (cachedSuperclass == null) cachedSuperclass = constPool.getClassInfo(superClass);
+      return cachedSuperclass;
+   }
+
+   /**
+    * Returns the index of the constant pool entry representing
+    * the super class.
+    */
+   public int getSuperclassId()
+   {
+      return superClass;
+   }
+
+   /**
+    * Sets the super class.
+    * <p/>
+    * <p>This method modifies constructors so that they call
+    * constructors declared in the new super class.
+    */
+   public void setSuperclass(String superclass)
+           throws CannotCompileException
+   {
+      if (superclass == null)
+         superclass = "java.lang.Object";
+
+      try
+      {
+         this.superClass = constPool.addClassInfo(superclass);
+         ArrayList list = methods;
+         int n = list.size();
+         for (int i = 0; i < n; ++i)
+         {
+            MethodInfo minfo = (MethodInfo) list.get(i);
+            minfo.setSuperclass(superclass);
+         }
+      }
+      catch (BadBytecode e)
+      {
+         throw new CannotCompileException(e);
+      }
+      cachedSuperclass = superclass;
+   }
+
+   /**
+    * Replaces all occurrences of a class name in the class file.
+    * <p/>
+    * <p>If class X is substituted for class Y in the class file,
+    * X and Y must have the same signature.  If Y provides a method
+    * m(), X must provide it even if X inherits m() from the super class.
+    * If this fact is not guaranteed, the bytecode verifier may cause
+    * an error.
+    *
+    * @param oldname the replaced class name
+    * @param newname the substituted class name
+    */
+   public final void renameClass(String oldname, String newname)
+   {
+      ArrayList list;
+      int n;
+
+      if (oldname.equals(newname))
+         return;
+
+      if (oldname.equals(thisclassname))
+         thisclassname = newname;
+
+      oldname = Descriptor.toJvmName(oldname);
+      newname = Descriptor.toJvmName(newname);
+      constPool.renameClass(oldname, newname);
+
+      list = methods;
+      n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         String desc = minfo.getDescriptor();
+         minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+      }
+
+      list = fields;
+      n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         FieldInfo finfo = (FieldInfo) list.get(i);
+         String desc = finfo.getDescriptor();
+         finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
+      }
+   }
+
+   /**
+    * Replaces all occurrences of several class names in the class file.
+    *
+    * @param classnames specifies which class name is replaced
+    *                   with which new name.  Class names must
+    *                   be described with the JVM-internal
+    *                   representation like
+    *                   <code>java/lang/Object</code>.
+    * @see #renameClass(String,String)
+    */
+   public final void renameClass(Map classnames)
+   {
+      String jvmNewThisName
+              = (String) classnames.get(Descriptor.toJvmName(thisclassname));
+      if (jvmNewThisName != null)
+         thisclassname = Descriptor.toJavaName(jvmNewThisName);
+
+      constPool.renameClass(classnames);
+
+      ArrayList list = methods;
+      int n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         String desc = minfo.getDescriptor();
+         minfo.setDescriptor(Descriptor.rename(desc, classnames));
+      }
+
+      list = fields;
+      n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         FieldInfo finfo = (FieldInfo) list.get(i);
+         String desc = finfo.getDescriptor();
+         finfo.setDescriptor(Descriptor.rename(desc, classnames));
+      }
+   }
+
+   /**
+    * Returns the names of the interfaces implemented by the class.
+    */
+   public String[] getInterfaces()
+   {
+      if (cachedInterfaces != null) return cachedInterfaces;
+      String[] rtn = null;
+      if (interfaces == null)
+         rtn = new String[0];
+      else
+      {
+         int n = interfaces.length;
+         String[] list = new String[n];
+         for (int i = 0; i < n; ++i)
+            list[i] = constPool.getClassInfo(interfaces[i]);
+
+         rtn = list;
+      }
+      cachedInterfaces = rtn;
+      return rtn;
+   }
+
+   /**
+    * Sets the interfaces.
+    *
+    * @param nameList the names of the interfaces.
+    */
+   public void setInterfaces(String[] nameList)
+   {
+      cachedInterfaces = null;
+      if (nameList != null)
+      {
+         int n = nameList.length;
+         interfaces = new int[n];
+         for (int i = 0; i < n; ++i)
+            interfaces[i] = constPool.addClassInfo(nameList[i]);
+      }
+   }
+
+   /**
+    * Appends an interface to the
+    * interfaces implemented by the class.
+    */
+   public void addInterface(String name)
+   {
+      cachedInterfaces = null;
+      int info = constPool.addClassInfo(name);
+      if (interfaces == null)
+      {
+         interfaces = new int[1];
+         interfaces[0] = info;
+      }
+      else
+      {
+         int n = interfaces.length;
+         int[] newarray = new int[n + 1];
+         System.arraycopy(interfaces, 0, newarray, 0, n);
+         newarray[n] = info;
+         interfaces = newarray;
+      }
+   }
+
+   /**
+    * Returns all the fields declared in the class.
+    *
+    * @return a list of <code>FieldInfo</code>.
+    * @see FieldInfo
+    */
+   public List getFields()
+   {
+      return fields;
+   }
+
+   /**
+    * Appends a field to the class.
+    */
+   public void addField(FieldInfo finfo) throws CannotCompileException
+   {
+      testExistingField(finfo.getName(), finfo.getDescriptor());
+      fields.add(finfo);
+   }
+
+   private void addField0(FieldInfo finfo)
+   {
+      fields.add(finfo);
+   }
+
+   private void testExistingField(String name, String descriptor)
+           throws CannotCompileException
+   {
+      ListIterator it = fields.listIterator(0);
+      while (it.hasNext())
+      {
+         FieldInfo minfo = (FieldInfo) it.next();
+         if (minfo.getName().equals(name))
+            throw new CannotCompileException("duplicate field: " + name);
+      }
+   }
+
+   /**
+    * Returns all the methods declared in the class.
+    *
+    * @return a list of <code>MethodInfo</code>.
+    * @see MethodInfo
+    */
+   public List getMethods()
+   {
+      return methods;
+   }
+
+   /**
+    * Returns the method with the specified name.  If there are multiple
+    * methods with that name, this method returns one of them.
+    *
+    * @return null             if no such a method is found.
+    */
+   public MethodInfo getMethod(String name)
+   {
+      ArrayList list = methods;
+      int n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         if (minfo.getName().equals(name))
+            return minfo;
+      }
+
+      return null;
+   }
+
+   /**
+    * Returns a static initializer (class initializer), or null if
+    * it does not exist.
+    */
+   public MethodInfo getStaticInitializer()
+   {
+      return getMethod(MethodInfo.nameClinit);
+   }
+
+   /**
+    * Appends a method to the class.
+    */
+   public void addMethod(MethodInfo minfo) throws CannotCompileException
+   {
+      testExistingMethod(minfo.getName(), minfo.getDescriptor());
+      methods.add(minfo);
+   }
+
+   private void addMethod0(MethodInfo minfo)
+   {
+      methods.add(minfo);
+   }
+
+   private void testExistingMethod(String name, String descriptor)
+           throws CannotCompileException
+   {
+      ListIterator it = methods.listIterator(0);
+      while (it.hasNext())
+      {
+         MethodInfo minfo = (MethodInfo) it.next();
+         if (minfo.getName().equals(name)
+             && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor))
+            throw new CannotCompileException("duplicate method: " + name);
+      }
+   }
+
+   /**
+    * Returns all the attributes.
+    *
+    * @return a list of <code>AttributeInfo</code> objects.
+    * @see AttributeInfo
+    */
+   public List getAttributes()
+   {
+      return attributes;
+   }
+
+   /**
+    * Returns the attribute with the specified name.
+    *
+    * @param name attribute name
+    */
+   public AttributeInfo getAttribute(String name)
+   {
+      LinkedList list = attributes;
+      int n = list.size();
+      for (int i = 0; i < n; ++i)
+      {
+         AttributeInfo ai = (AttributeInfo) list.get(i);
+         if (ai.getName().equals(name))
+            return ai;
+      }
+
+      return null;
+   }
+
+   /**
+    * Appends an attribute.  If there is already an attribute with
+    * the same name, the new one substitutes for it.
+    */
+   public void addAttribute(AttributeInfo info)
+   {
+      AttributeInfo.remove(attributes, info.getName());
+      attributes.add(info);
+   }
+
+   /**
+    * Returns the source file containing this class.
+    *
+    * @return null     if this information is not available.
+    */
+   public String getSourceFile()
+   {
+      SourceFileAttribute sf
+              = (SourceFileAttribute) getAttribute(SourceFileAttribute.tag);
+      if (sf == null)
+         return null;
+      else
+         return sf.getFileName();
+   }
+
+   private void read(DataInputStream in) throws IOException
+   {
+      int i, n;
+      int magic = in.readInt();
+      if (magic != 0xCAFEBABE)
+         throw new IOException("non class file");
+
+      minor = in.readUnsignedShort();
+      major = in.readUnsignedShort();
+      constPool = new ConstPool(in);
+      accessFlags = in.readUnsignedShort();
+      thisClass = in.readUnsignedShort();
+      constPool.setThisClassInfo(thisClass);
+      superClass = in.readUnsignedShort();
+      n = in.readUnsignedShort();
+      if (n == 0)
+         interfaces = null;
+      else
+      {
+         interfaces = new int[n];
+         for (i = 0; i < n; ++i)
+            interfaces[i] = in.readUnsignedShort();
+      }
+
+      ConstPool cp = constPool;
+      n = in.readUnsignedShort();
+      fields = new ArrayList();
+      for (i = 0; i < n; ++i)
+         addField0(new FieldInfo(cp, in));
+
+      n = in.readUnsignedShort();
+      methods = new ArrayList();
+      for (i = 0; i < n; ++i)
+         addMethod0(new MethodInfo(cp, in));
+
+      attributes = new LinkedList();
+      n = in.readUnsignedShort();
+      for (i = 0; i < n; ++i)
+         addAttribute(AttributeInfo.read(cp, in));
+
+      thisclassname = constPool.getClassInfo(thisClass);
+   }
+
+   /**
+    * Writes a class file represened by this object
+    * into an output stream.
+    */
+   public void write(DataOutputStream out) throws IOException
+   {
+      int i, n;
+
+      out.writeInt(0xCAFEBABE);       // magic
+      out.writeShort(minor);          // minor version
+      out.writeShort(major);          // major version
+      constPool.write(out);           // constant pool
+      out.writeShort(accessFlags);
+      out.writeShort(thisClass);
+      out.writeShort(superClass);
+
+      if (interfaces == null)
+         n = 0;
+      else
+         n = interfaces.length;
+
+      out.writeShort(n);
+      for (i = 0; i < n; ++i)
+         out.writeShort(interfaces[i]);
+
+      ArrayList list = fields;
+      n = list.size();
+      out.writeShort(n);
+      for (i = 0; i < n; ++i)
+      {
+         FieldInfo finfo = (FieldInfo) list.get(i);
+         finfo.write(out);
+      }
+
+      list = methods;
+      n = list.size();
+      out.writeShort(n);
+      for (i = 0; i < n; ++i)
+      {
+         MethodInfo minfo = (MethodInfo) list.get(i);
+         minfo.write(out);
+      }
+
+      out.writeShort(attributes.size());
+      AttributeInfo.writeAll(attributes, out);
+   }
+
+   /**
+    * Get the Major version.
+    *
+    * @return the major version
+    */
+   public int getMajorVersion()
+   {
+      return major;
+   }
+
+   /**
+    * Set the Major version.
+    *
+    * @param major the major version
+    */
+   public void setMajorVersion(int major)
+   {
+      this.major = major;
+   }
+
+   /**
+    * Get the Minor version.
+    *
+    * @return the minor version
+    */
+   public int getMinorVersion()
+   {
+      return minor;
+   }
+
+   /**
+    * Set the Minor version.
+    *
+    * @param minor the minor version
+    */
+   public void setMinorVersion(int minor)
+   {
+      this.minor = minor;
+   }
 }
index 02c73a321317a584ce2d6c3469ce5278eb07ab8a..21ec3ffbaddd6701e405d441c4dd51015f1e5685 100644 (file)
@@ -30,6 +30,8 @@ public final class FieldInfo {
     ConstPool constPool;
     int accessFlags;
     int name;
+   String cachedName;
+   String cachedType;
     int descriptor;
     LinkedList attribute;       // may be null.
 
@@ -51,6 +53,7 @@ public final class FieldInfo {
     public FieldInfo(ConstPool cp, String fieldName, String desc) {
         this(cp);
         name = cp.addUtf8Info(fieldName);
+       cachedName = fieldName;
         descriptor = cp.addUtf8Info(desc);
     }
 
@@ -75,12 +78,24 @@ public final class FieldInfo {
     }
 
     void prune(ConstPool cp) {
+       AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
+       LinkedList newAttributes = new LinkedList();
+       if (invisibleAnnotations != null)
+       {
+          invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+          newAttributes.add(invisibleAnnotations);
+       }
+       AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
+       if (visibleAnnotations != null)
+       {
+          visibleAnnotations = visibleAnnotations.copy(cp, null);
+          newAttributes.add(visibleAnnotations);
+       }
         int index = getConstantValue();
-        if (index == 0)
-            attribute = null;
-        else {
+        attribute = newAttributes;
+        if (index != 0)
+        {
             index = constPool.copy(index, cp, null);
-            attribute = new LinkedList();
             attribute.add(new ConstantAttribute(cp, index));
         }
 
@@ -101,7 +116,8 @@ public final class FieldInfo {
      * Returns the field name.
      */
     public String getName() {
-        return constPool.getUtf8Info(name);
+       if (cachedName == null) cachedName = constPool.getUtf8Info(name);
+       return cachedName;
     }
 
     /**
@@ -109,6 +125,7 @@ public final class FieldInfo {
      */
     public void setName(String newName) {
         name = constPool.addUtf8Info(newName);
+       cachedName = newName;
     }
 
     /**
index ffc7fcfc898eaa151000b0ddb041a7c95765569e..ef94be444862e4d971ac796e222af98994457910 100644 (file)
@@ -32,6 +32,7 @@ public final class MethodInfo {
     ConstPool constPool;
     int accessFlags;
     int name;
+   String cachedName;
     int descriptor;
     LinkedList attribute; // may be null
 
@@ -70,6 +71,7 @@ public final class MethodInfo {
         this(cp);
         accessFlags = 0;
         name = cp.addUtf8Info(methodname);
+        cachedName = methodname;
         descriptor = constPool.addUtf8Info(desc);
     }
 
@@ -107,7 +109,7 @@ public final class MethodInfo {
      * Returns a string representation of the object.
      */
     public String toString() {
-        return constPool.getUtf8Info(name) + " "
+        return getName() + " "
                 + constPool.getUtf8Info(descriptor);
     }
 
@@ -127,7 +129,23 @@ public final class MethodInfo {
     }
 
     void prune(ConstPool cp) {
-        attribute = null;
+       AttributeInfo invisibleAnnotations = getAttribute(AnnotationsAttribute.invisibleTag);
+       LinkedList newAttributes = new LinkedList();
+       if (invisibleAnnotations != null)
+       {
+          invisibleAnnotations = invisibleAnnotations.copy(cp, null);
+          newAttributes.add(invisibleAnnotations);
+       }
+       AttributeInfo visibleAnnotations = getAttribute(AnnotationsAttribute.visibleTag);
+       if (visibleAnnotations != null)
+       {
+          visibleAnnotations = visibleAnnotations.copy(cp, null);
+          newAttributes.add(visibleAnnotations);
+       }
+       ExceptionsAttribute ea = getExceptionsAttribute();
+       if (ea != null) newAttributes.add(ea);
+       
+        attribute = newAttributes;
         name = cp.addUtf8Info(getName());
         descriptor = cp.addUtf8Info(getDescriptor());
         constPool = cp;
@@ -137,7 +155,8 @@ public final class MethodInfo {
      * Returns a method name.
      */
     public String getName() {
-        return constPool.getUtf8Info(name);
+       if (cachedName == null) cachedName = constPool.getUtf8Info(name);
+       return cachedName;
     }
 
     /**
@@ -145,6 +164,7 @@ public final class MethodInfo {
      */
     public void setName(String newName) {
         name = constPool.addUtf8Info(newName);
+       cachedName = newName;
     }
 
     /**
@@ -383,7 +403,7 @@ public final class MethodInfo {
         ConstPool destCp = constPool;
         accessFlags = src.accessFlags;
         name = destCp.addUtf8Info(methodname);
-
+        cachedName = methodname;
         ConstPool srcCp = src.constPool;
         String desc = srcCp.getUtf8Info(src.descriptor);
         String desc2 = Descriptor.rename(desc, classnames);