diff options
author | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2005-01-12 16:09:47 +0000 |
---|---|---|
committer | chiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3> | 2005-01-12 16:09:47 +0000 |
commit | e793a77000f14fd8272388f7b2878a54e2d628ca (patch) | |
tree | 47c705d645288afd4bc39a87a4baf80154222401 /src/main | |
parent | 91895bb38cf5cf4feaf8dcb3ba76555d67d765db (diff) | |
download | javassist-e793a77000f14fd8272388f7b2878a54e2d628ca.tar.gz javassist-e793a77000f14fd8272388f7b2878a54e2d628ca.zip |
implemented removeMethod() etc.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@151 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/javassist/CtClass.java | 34 | ||||
-rw-r--r-- | src/main/javassist/CtClassType.java | 128 | ||||
-rw-r--r-- | src/main/javassist/CtConstructor.java | 26 | ||||
-rw-r--r-- | src/main/javassist/CtField.java | 33 | ||||
-rw-r--r-- | src/main/javassist/CtMember.java | 44 | ||||
-rw-r--r-- | src/main/javassist/CtMethod.java | 25 | ||||
-rw-r--r-- | src/main/javassist/bytecode/AttributeInfo.java | 14 | ||||
-rw-r--r-- | src/main/javassist/bytecode/ClassFile.java | 42 | ||||
-rw-r--r-- | src/main/javassist/bytecode/CodeAttribute.java | 7 | ||||
-rw-r--r-- | src/main/javassist/bytecode/FieldInfo.java | 15 | ||||
-rw-r--r-- | src/main/javassist/bytecode/MethodInfo.java | 19 |
11 files changed, 251 insertions, 136 deletions
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java index 29512ace..78b40150 100644 --- a/src/main/javassist/CtClass.java +++ b/src/main/javassist/CtClass.java @@ -44,7 +44,7 @@ public abstract class CtClass { /** * The version number of this release. */ - public static final String version = "3.0 RC1"; + public static final String version = "3.0"; /** * Prints the version number and the copyright notice. @@ -55,7 +55,7 @@ public abstract class CtClass { */ public static void main(String[] args) { System.out.println("Javassist version " + CtClass.version); - System.out.println("Copyright (C) 1999-2004 Shigeru Chiba." + System.out.println("Copyright (C) 1999-2005 Shigeru Chiba." + " All Rights Reserved."); } @@ -747,6 +747,16 @@ public abstract class CtClass { } /** + * Removes a constructor declared in this class. + * + * @param c removed constructor. + * @throws NotFoundException if the constructor is not found. + */ + public void removeConstructor(CtConstructor c) throws NotFoundException { + checkModify(); + } + + /** * Adds a method. */ public void addMethod(CtMethod m) throws CannotCompileException { @@ -754,6 +764,16 @@ public abstract class CtClass { } /** + * Removes a method declared in this class. + * + * @param m removed method. + * @throws NotFoundException if the method is not found. + */ + public void removeMethod(CtMethod m) throws NotFoundException { + checkModify(); + } + + /** * Adds a field. * * <p>The <code>CtField</code> belonging to another @@ -826,6 +846,16 @@ public abstract class CtClass { } /** + * Removes a field declared in this class. + * + * @param f removed field. + * @throws NotFoundException if the field is not found. + */ + public void removeField(CtField f) throws NotFoundException { + checkModify(); + } + + /** * Obtains an attribute with the given name. * If that attribute is not found in the class file, this * method returns null. diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java index 5b249a42..d567a9b9 100644 --- a/src/main/javassist/CtClassType.java +++ b/src/main/javassist/CtClassType.java @@ -52,12 +52,13 @@ class CtClassType extends CtClass { boolean wasChanged; private boolean wasFrozen; boolean wasPruned; + boolean memberRemoved; ClassFile classfile; - private CtField fieldsCache; - private CtConstructor constructorsCache; + private CtMember fieldsCache; + private CtMember methodsCache; + private CtMember constructorsCache; private CtConstructor classInitializerCache; - private CtMethod methodsCache; private AccessorMaker accessors; @@ -73,7 +74,7 @@ class CtClassType extends CtClass { CtClassType(String name, ClassPool cp) { super(name); classPool = cp; - wasChanged = wasFrozen = wasPruned = false; + wasChanged = wasFrozen = wasPruned = memberRemoved = false; classfile = null; accessors = null; fieldInitializers = null; @@ -129,7 +130,7 @@ class CtClassType extends CtClass { buffer.append(" extends ??"); } - CtField field = getFieldsCache(); + CtMember field = getFieldsCache(); buffer.append(" fields="); while (field != null) { buffer.append(field); @@ -137,7 +138,7 @@ class CtClassType extends CtClass { field = field.next; } - CtConstructor c = getConstructorsCache(); + CtMember c = getConstructorsCache(); buffer.append(" constructors="); while (c != null) { buffer.append(c); @@ -145,7 +146,7 @@ class CtClassType extends CtClass { c = c.next; } - CtMethod m = getMethodsCache(); + CtMember m = getMethodsCache(); buffer.append(" methods="); while (m != null) { buffer.append(m); @@ -471,7 +472,7 @@ class CtClassType extends CtClass { } catch (NotFoundException e) {} - CtField cf = ((CtClassType)cc).getFieldsCache(); + CtMember cf = ((CtClassType)cc).getFieldsCache(); while (cf != null) { if (Modifier.isPublic(cf.getModifiers())) alist.add(cf); @@ -511,25 +512,25 @@ class CtClassType extends CtClass { } public CtField[] getDeclaredFields() { - CtField cf = getFieldsCache(); + CtMember cf = getFieldsCache(); int num = CtField.count(cf); CtField[] cfs = new CtField[num]; int i = 0; while (cf != null) { - cfs[i++] = cf; + cfs[i++] = (CtField)cf; cf = cf.next; } return cfs; } - protected CtField getFieldsCache() { + protected CtMember getFieldsCache() { if (fieldsCache == null) { List list = getClassFile2().getFields(); int n = list.size(); for (int i = 0; i < n; ++i) { FieldInfo finfo = (FieldInfo)list.get(i); - fieldsCache = CtField.append(fieldsCache, + fieldsCache = CtMember.append(fieldsCache, new CtField(finfo, this)); } } @@ -546,10 +547,10 @@ class CtClassType extends CtClass { } private CtField getDeclaredField2(String name) { - CtField cf = getFieldsCache(); + CtMember cf = getFieldsCache(); while (cf != null) { if (cf.getName().equals(name)) - return cf; + return (CtField)cf; cf = cf.next; } @@ -558,18 +559,18 @@ class CtClassType extends CtClass { } public CtBehavior[] getDeclaredBehaviors() { - CtConstructor cc = getConstructorsCache(); - CtMethod cm = getMethodsCache(); - int num = CtMethod.count(cm) + CtConstructor.count(cc); + CtMember cc = getConstructorsCache(); + CtMember cm = getMethodsCache(); + int num = CtMember.count(cm) + CtMember.count(cc); CtBehavior[] cb = new CtBehavior[num]; int i = 0; while (cc != null) { - cb[i++] = cc; + cb[i++] = (CtBehavior)cc; cc = cc.next; } while (cm != null) { - cb[i++] = cm; + cb[i++] = (CtBehavior)cm; cm = cm.next; } @@ -602,31 +603,31 @@ class CtClassType extends CtClass { public CtConstructor getConstructor(String desc) throws NotFoundException { - CtConstructor cc = getConstructorsCache(); + CtConstructor cc = (CtConstructor)getConstructorsCache(); while (cc != null) { if (cc.getMethodInfo2().getDescriptor().equals(desc)) return cc; - cc = cc.next; + cc = (CtConstructor)cc.next; } return super.getConstructor(desc); } public CtConstructor[] getDeclaredConstructors() { - CtConstructor cc = getConstructorsCache(); - int num = CtConstructor.count(cc); + CtMember cc = getConstructorsCache(); + int num = CtMember.count(cc); CtConstructor[] ccs = new CtConstructor[num]; int i = 0; while (cc != null) { - ccs[i++] = cc; + ccs[i++] = (CtConstructor)cc; cc = cc.next; } return ccs; } - protected CtConstructor getConstructorsCache() { + protected CtMember getConstructorsCache() { if (constructorsCache == null) { List list = getClassFile2().getMethods(); int n = list.size(); @@ -634,8 +635,8 @@ class CtClassType extends CtClass { MethodInfo minfo = (MethodInfo)list.get(i); if (minfo.isConstructor()) constructorsCache - = CtConstructor.append(constructorsCache, - new CtConstructor(minfo, this)); + = CtMember.append(constructorsCache, + new CtConstructor(minfo, this)); } } @@ -675,10 +676,10 @@ class CtClassType extends CtClass { catch (NotFoundException e) {} if (cc instanceof CtClassType) { - CtMethod cm = ((CtClassType)cc).getMethodsCache(); + CtMember cm = ((CtClassType)cc).getMethodsCache(); while (cm != null) { if (Modifier.isPublic(cm.getModifiers())) - h.put(cm.getStringRep(), cm); + h.put(((CtMethod)cm).getStringRep(), cm); cm = cm.next; } @@ -699,13 +700,13 @@ class CtClassType extends CtClass { private static CtMethod getMethod0(CtClass cc, String name, String desc) { if (cc instanceof CtClassType) { - CtMethod cm = ((CtClassType)cc).getMethodsCache(); + CtMethod cm = (CtMethod)((CtClassType)cc).getMethodsCache(); while (cm != null) { if (cm.getName().equals(name) && cm.getMethodInfo2().getDescriptor().equals(desc)) return cm; - cm = cm.next; + cm = (CtMethod)cm.next; } } @@ -733,12 +734,12 @@ class CtClassType extends CtClass { } public CtMethod[] getDeclaredMethods() { - CtMethod cm = getMethodsCache(); - int num = CtMethod.count(cm); + CtMember cm = getMethodsCache(); + int num = CtMember.count(cm); CtMethod[] cms = new CtMethod[num]; int i = 0; while (cm != null) { - cms[i++] = cm; + cms[i++] = (CtMethod)cm; cm = cm.next; } @@ -746,10 +747,10 @@ class CtClassType extends CtClass { } public CtMethod getDeclaredMethod(String name) throws NotFoundException { - CtMethod m = getMethodsCache(); + CtMember m = getMethodsCache(); while (m != null) { if (m.getName().equals(name)) - return m; + return (CtMethod)m; m = m.next; } @@ -762,28 +763,28 @@ class CtClassType extends CtClass { throws NotFoundException { String desc = Descriptor.ofParameters(params); - CtMethod m = getMethodsCache(); + CtMethod m = (CtMethod)getMethodsCache(); while (m != null) { if (m.getName().equals(name) && m.getMethodInfo2().getDescriptor().startsWith(desc)) return m; - m = m.next; + m = (CtMethod)m.next; } throw new NotFoundException(name + "(..) is not found in " + getName()); } - protected CtMethod getMethodsCache() { + protected CtMember getMethodsCache() { if (methodsCache == null) { List list = getClassFile2().getMethods(); int n = list.size(); for (int i = 0; i < n; ++i) { MethodInfo minfo = (MethodInfo)list.get(i); if (minfo.isMethod()) - methodsCache = CtMethod.append(methodsCache, - new CtMethod(minfo, this)); + methodsCache = CtMember.append(methodsCache, + new CtMethod(minfo, this)); } } @@ -824,6 +825,18 @@ class CtClassType extends CtClass { } } + public void removeField(CtField f) throws NotFoundException { + checkModify(); + FieldInfo fi = f.getFieldInfo2(); + ClassFile cf = getClassFile2(); + if (cf.getFields().remove(fi)) { + fieldsCache = CtMember.remove(fieldsCache, f); + memberRemoved = true; + } + else + throw new NotFoundException(f.toString()); + } + public CtConstructor makeClassInitializer() throws CannotCompileException { @@ -846,22 +859,46 @@ class CtClassType extends CtClass { throw new CannotCompileException("cannot add"); getConstructorsCache(); - constructorsCache = CtConstructor.append(constructorsCache, c); + constructorsCache = (CtConstructor)CtMember.append(constructorsCache, c); getClassFile2().addMethod(c.getMethodInfo2()); } + public void removeConstructor(CtConstructor m) throws NotFoundException { + checkModify(); + MethodInfo mi = m.getMethodInfo2(); + ClassFile cf = getClassFile2(); + if (cf.getMethods().remove(mi)) { + constructorsCache = CtMember.remove(constructorsCache, m); + memberRemoved = true; + } + else + throw new NotFoundException(m.toString()); + } + public void addMethod(CtMethod m) throws CannotCompileException { checkModify(); if (m.getDeclaringClass() != this) throw new CannotCompileException("cannot add"); getMethodsCache(); - methodsCache = CtMethod.append(methodsCache, m); + methodsCache = CtMember.append(methodsCache, m); getClassFile2().addMethod(m.getMethodInfo2()); if ((m.getModifiers() & Modifier.ABSTRACT) != 0) setModifiers(getModifiers() | Modifier.ABSTRACT); } + public void removeMethod(CtMethod m) throws NotFoundException { + checkModify(); + MethodInfo mi = m.getMethodInfo2(); + ClassFile cf = getClassFile2(); + if (cf.getMethods().remove(mi)) { + methodsCache = CtMember.remove(methodsCache, m); + memberRemoved = true; + } + else + throw new NotFoundException(m.toString()); + } + public byte[] getAttribute(String name) { AttributeInfo ai = getClassFile2().getAttribute(name); if (ai == null) @@ -910,6 +947,11 @@ class CtClassType extends CtClass { if (isModified()) { checkPruned("toBytecode"); ClassFile cf = getClassFile2(); + if (memberRemoved) { + cf.compact(); + memberRemoved = false; + } + modifyClassConstructor(cf); modifyConstructors(cf); cf.write(out); diff --git a/src/main/javassist/CtConstructor.java b/src/main/javassist/CtConstructor.java index cac15b36..707d6863 100644 --- a/src/main/javassist/CtConstructor.java +++ b/src/main/javassist/CtConstructor.java @@ -33,8 +33,6 @@ import javassist.compiler.CompileError; * @see CtNewConstructor */ public final class CtConstructor extends CtBehavior { - protected CtConstructor next; - protected CtConstructor(MethodInfo minfo, CtClass declaring) { super(declaring, minfo); next = null; @@ -132,30 +130,6 @@ public final class CtConstructor extends CtBehavior { } } - static CtConstructor append(CtConstructor list, CtConstructor tail) { - tail.next = null; - if (list == null) - return tail; - else { - CtConstructor lst = list; - while (lst.next != null) - lst = lst.next; - - lst.next = tail; - return list; - } - } - - static int count(CtConstructor m) { - int n = 0; - while (m != null) { - ++n; - m = m.next; - } - - return n; - } - /** * Returns true if this object represents a constructor. */ diff --git a/src/main/javassist/CtField.java b/src/main/javassist/CtField.java index c537ed58..cfda5a22 100644 --- a/src/main/javassist/CtField.java +++ b/src/main/javassist/CtField.java @@ -27,7 +27,6 @@ import javassist.compiler.ast.ASTree; */ public class CtField extends CtMember { protected FieldInfo fieldInfo; - CtField next; /** * Creates a <code>CtField</code> object. @@ -98,6 +97,14 @@ public class CtField extends CtMember { next = null; } + /** + * Returns a String representation of the object. + */ + public String toString() { + return getDeclaringClass().getName() + "." + getName() + + ":" + fieldInfo.getDescriptor(); + } + protected void extendToString(StringBuffer buffer) { buffer.append(' '); buffer.append(getName()); @@ -149,30 +156,6 @@ public class CtField extends CtMember { throw new CannotCompileException("not a field"); } - static CtField append(CtField list, CtField tail) { - tail.next = null; - if (list == null) - return tail; - else { - CtField lst = list; - while (lst.next != null) - lst = lst.next; - - lst.next = tail; - return list; - } - } - - static int count(CtField f) { - int n = 0; - while (f != null) { - ++n; - f = f.next; - } - - return n; - } - /** * Returns the FieldInfo representing the field in the class file. */ diff --git a/src/main/javassist/CtMember.java b/src/main/javassist/CtMember.java index 05d02bf8..59741352 100644 --- a/src/main/javassist/CtMember.java +++ b/src/main/javassist/CtMember.java @@ -20,10 +20,54 @@ package javassist; * or a method. */ public abstract class CtMember { + protected CtMember next; // for internal use protected CtClass declaringClass; protected CtMember(CtClass clazz) { declaringClass = clazz; } + 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) { + int n = 0; + while (f != null) { + ++n; + f = f.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; + break; + } + + list = list.next; + } + + return top; + } + public String toString() { StringBuffer buffer = new StringBuffer(getClass().getName()); buffer.append("@"); diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java index 9d9416b3..8195e9b4 100644 --- a/src/main/javassist/CtMethod.java +++ b/src/main/javassist/CtMethod.java @@ -27,7 +27,6 @@ import javassist.bytecode.*; * @see CtNewMethod */ public final class CtMethod extends CtBehavior { - protected CtMethod next; protected String cachedStringRep; CtMethod(MethodInfo minfo, CtClass declaring) { @@ -133,30 +132,6 @@ public final class CtMethod extends CtBehavior { } } - static CtMethod append(CtMethod list, CtMethod tail) { - tail.next = null; - if (list == null) - return tail; - else { - CtMethod lst = list; - while (lst.next != null) - lst = lst.next; - - lst.next = tail; - return list; - } - } - - static int count(CtMethod m) { - int n = 0; - while (m != null) { - ++n; - m = m.next; - } - - return n; - } - /** * Returns a hash code value for the method. * If two methods have the same name and signature, then diff --git a/src/main/javassist/bytecode/AttributeInfo.java b/src/main/javassist/bytecode/AttributeInfo.java index 28b01846..06d89904 100644 --- a/src/main/javassist/bytecode/AttributeInfo.java +++ b/src/main/javassist/bytecode/AttributeInfo.java @@ -222,4 +222,18 @@ public class AttributeInfo { attr.write(out); } } + + static LinkedList copyAll(LinkedList list, ConstPool cp) { + if (list == null) + return null; + + LinkedList newList = new LinkedList(); + int n = list.size(); + for (int i = 0; i < n; ++i) { + AttributeInfo attr = (AttributeInfo)list.get(i); + newList.add(attr.copy(cp, null)); + } + + return newList; + } } diff --git a/src/main/javassist/bytecode/ClassFile.java b/src/main/javassist/bytecode/ClassFile.java index 4f85f667..5c4bc1cc 100644 --- a/src/main/javassist/bytecode/ClassFile.java +++ b/src/main/javassist/bytecode/ClassFile.java @@ -99,13 +99,33 @@ public final class ClassFile { } /** - * 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). + * 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 prune() { + 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) { @@ -115,6 +135,18 @@ public final class ClassFile { = 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) { diff --git a/src/main/javassist/bytecode/CodeAttribute.java b/src/main/javassist/bytecode/CodeAttribute.java index 4c7e27bb..97742d8a 100644 --- a/src/main/javassist/bytecode/CodeAttribute.java +++ b/src/main/javassist/bytecode/CodeAttribute.java @@ -82,19 +82,14 @@ public class CodeAttribute extends AttributeInfo implements Opcode { maxLocals = src.getMaxLocals(); exceptions = src.getExceptionTable().copy(cp, classnames); info = src.copyCode(cp, classnames, exceptions, this); - attributes = new LinkedList(); - /* Since an index into the source constant pool table may not - be translated, we don't copy the attributes. - */ - /* + attributes = new LinkedList(); List src_attr = src.getAttributes(); int num = src_attr.size(); for (int i = 0; i < num; ++i) { AttributeInfo ai = (AttributeInfo)src_attr.get(i); attributes.add(ai.copy(cp, classnames)); } - */ } CodeAttribute(ConstPool cp, int name_id, DataInputStream in) diff --git a/src/main/javassist/bytecode/FieldInfo.java b/src/main/javassist/bytecode/FieldInfo.java index ff45f1ba..8c2ed0a1 100644 --- a/src/main/javassist/bytecode/FieldInfo.java +++ b/src/main/javassist/bytecode/FieldInfo.java @@ -59,6 +59,21 @@ public final class FieldInfo { read(in); } + /** + * Copies all constant pool items to a given new constant pool + * and replaces the original items with the new ones. + * This is used for garbage collecting the items of removed fields + * and methods. + * + * @param cp the destination + */ + void compact(ConstPool cp) { + name = cp.addUtf8Info(getName()); + descriptor = cp.addUtf8Info(getDescriptor()); + attribute = AttributeInfo.copyAll(attribute, cp); + constPool = cp; + } + void prune(ConstPool cp) { int index = getConstantValue(); if (index == 0) diff --git a/src/main/javassist/bytecode/MethodInfo.java b/src/main/javassist/bytecode/MethodInfo.java index 3f3d93ef..3889fe54 100644 --- a/src/main/javassist/bytecode/MethodInfo.java +++ b/src/main/javassist/bytecode/MethodInfo.java @@ -30,13 +30,9 @@ import java.util.Map; */ public final class MethodInfo { ConstPool constPool; - int accessFlags; - int name; - int descriptor; - LinkedList attribute; // may be null // Bill, do you really need this? @@ -115,6 +111,21 @@ public final class MethodInfo { + constPool.getUtf8Info(descriptor); } + /** + * Copies all constant pool items to a given new constant pool + * and replaces the original items with the new ones. + * This is used for garbage collecting the items of removed fields + * and methods. + * + * @param cp the destination + */ + void compact(ConstPool cp) { + name = cp.addUtf8Info(getName()); + descriptor = cp.addUtf8Info(getDescriptor()); + attribute = AttributeInfo.copyAll(attribute, cp); + constPool = cp; + } + void prune(ConstPool cp) { attribute = null; name = cp.addUtf8Info(getName()); |