Browse Source

implemented removeMethod() etc.


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@151 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
chiba 19 years ago
parent
commit
e793a77000

+ 1
- 1
License.html View File

@@ -353,7 +353,7 @@ MISCELLANEOUS.</B>
<P>The Original Code is Javassist.
<P>The Initial Developer of the Original Code is Shigeru Chiba.
Portions created by the Initial Developer are<BR>&nbsp;
Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
<P>Contributor(s): ______________________________________.

<P>Alternatively, the contents of this file may be used under the terms of

+ 5
- 3
Readme.html View File

@@ -7,7 +7,7 @@

<h1>Javassist version 3</h1>

<h3>Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.</h3>
<h3>Copyright (C) 2000-2005 by Shigeru Chiba, All rights reserved.</h3>

<p><br></p>

@@ -255,10 +255,12 @@ see javassist.Dump.

<h2>Changes</h2>

<p>- version 3.0
<p>- version 3.0 in January, 2005

<ul>
<li>The compiler now supports a synchronized statement.
<li>The compiler now supports synchronized statements and finally
clauses.
<li>You can now remove a method and a field.
</ul>

<p>- version 3.0 RC1 in September 13, 2004.

+ 32
- 2
src/main/javassist/CtClass.java View File

@@ -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.");
}

@@ -746,6 +746,16 @@ public abstract class CtClass {
checkModify();
}

/**
* 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.
*/
@@ -753,6 +763,16 @@ public abstract class CtClass {
checkModify();
}

/**
* 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.
*
@@ -825,6 +845,16 @@ public abstract class CtClass {
checkModify();
}

/**
* 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

+ 85
- 43
src/main/javassist/CtClassType.java View File

@@ -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);

+ 0
- 26
src/main/javassist/CtConstructor.java View File

@@ -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.
*/

+ 8
- 25
src/main/javassist/CtField.java View File

@@ -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.
*/

+ 44
- 0
src/main/javassist/CtMember.java View File

@@ -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("@");

+ 0
- 25
src/main/javassist/CtMethod.java View File

@@ -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

+ 14
- 0
src/main/javassist/bytecode/AttributeInfo.java View File

@@ -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;
}
}

+ 37
- 5
src/main/javassist/bytecode/ClassFile.java View File

@@ -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) {

+ 1
- 6
src/main/javassist/bytecode/CodeAttribute.java View File

@@ -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)

+ 15
- 0
src/main/javassist/bytecode/FieldInfo.java View File

@@ -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)

+ 15
- 4
src/main/javassist/bytecode/MethodInfo.java View File

@@ -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());

+ 1464
- 1444
tutorial/tutorial2.html
File diff suppressed because it is too large
View File


Loading…
Cancel
Save