diff options
-rw-r--r-- | License.html | 2 | ||||
-rw-r--r-- | Readme.html | 8 | ||||
-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 | ||||
-rw-r--r-- | tutorial/tutorial2.html | 2908 |
14 files changed, 1721 insertions, 1584 deletions
diff --git a/License.html b/License.html index f8d626da..7a734c3a 100644 --- a/License.html +++ b/License.html @@ -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> - 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 diff --git a/Readme.html b/Readme.html index 61572855..910429cf 100644 --- a/Readme.html +++ b/Readme.html @@ -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. 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()); diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html index 7ef1fedb..d8d7381d 100644 --- a/tutorial/tutorial2.html +++ b/tutorial/tutorial2.html @@ -1,1444 +1,1464 @@ -<html> -<head> - <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> - <title>Javassist Tutorial</title> - <link rel="stylesheet" type="text/css" href="brown.css"> -</head> - -<body> - -<div align="right">Getting Started with Javassist</div> - -<div align="left"><a href="tutorial.html">Previous page</a></div> -<div align="right"><a href="tutorial3.html">Next page</a></div> - -<p> -<a href="#intro">4. Introspection and customization</a> -<ul> -<li><a href="#before">Inserting source text at the beginning/end of a method body</a> -<br><li><a href="#alter">Altering a method body</a> -<br><li><a href="#add">Adding a new method or field</a> -<br><li><a href="#runtime">Runtime support classes</a> -<br><li><a href="#limit">Limitations</a> -</ul> - -<p><br> - -<a name="intro"> -<h2>4. Introspection and customization</h2> - -<p><code>CtClass</code> provides methods for introspection. The -introspective ability of Javassist is compatible with that of -the Java reflection API. <code>CtClass</code> provides -<code>getName()</code>, <code>getSuperclass()</code>, -<code>getMethods()</code>, and so on. -<code>CtClass</code> also provides methods for modifying a class -definition. It allows to add a new field, constructor, and method. -Instrumenting a method body is also possible. - -<p> -Methods are represented by <code>CtMethod</code> objects. -<code>CtMethod</code> provides several methods for modifying -the definition of the method. Note that if a method is inherited -from a super class, then -the same <code>CtMethod</code> object -that represents the inherited method represents the method declared -in that super class. -A <code>CtMethod</code> object corresponds to every method declaration. - -<p> -For example, if class <code>Point</code> declares method <code>move()</code> -and a subclass <code>ColorPoint</code> of <code>Point</code> does -not override <code>move()</code>, the two <code>move()</code> methods -declared in <code>Point</code> and inherited in <code>ColorPoint</code> -are represented by the identical <code>CtMethod</code> object. -If the method definition represented by this -<code>CtMethod</code> object is modified, the modification is -reflected on both the methods. -If you want to modify only the <code>move()</code> method in -<code>ColorPoint</code>, you first have to add to <code>ColorPoint</code> -a copy of the <code>CtMethod</code> object representing <code>move()</code> -in <code>Point</code>. A copy of the the <code>CtMethod</code> object -can be obtained by <code>CtNewMethod.copy()</code>. - - -<p><hr width="40%"> - -<ul> -Javassist does not allow to remove a method or field, but it allows -to change the name. So if a method is not necessary any more, it should be -renamed and changed to be a private method by calling -<code>setName()</code> -and <code>setModifiers()</code> declared in <code>CtMethod</code>. - -<p>Javassist does not allow to add an extra parameter to an existing -method, either. Instead of doing that, a new method receiving the -extra parameter as well as the other parameters should be added to the -same class. For example, if you want to add an extra <code>int</code> -parameter <code>newZ</code> to a method: - -<ul><pre>void move(int newX, int newY) { x = newX; y = newY; }</pre></ul> - -<p>in a <code>Point</code> class, then you should add the following -method to the <code>Point</code> class: - -<ul><pre>void move(int newX, int newY, int newZ) { - // do what you want with newZ. - move(newX, newY); -}</pre></ul> - -</ul> - -<p><hr width="40%"> - -<p>Javassist also provides low-level API for directly editing a raw -class file. For example, <code>getClassFile()</code> in -<code>CtClass</code> returns a <code>ClassFile</code> object -representing a raw class file. <code>getMethodInfo()</code> in -<code>CtMethod</code> returns a <code>MethodInfo</code> object -representing a <code>method_info</code> structure included in a class -file. The low-level API uses the vocabulary from the Java Virtual -machine specification. The users must have the knowledge about class -files and bytecode. For more details, the users should see the -<code>javassist.bytecode</code> package. - -<p>The class files modified by Javassist requires the -<code>javassist.runtime</code> package for runtime support -only if some special identifiers starting with <code>$</code> -are used. Those special identifiers are described below. -The class files modified without those special identifiers -do not need the <code>javassist.runtime</code> package or any -other Javassist packages at runtime. -For more details, see the API documentation -of the <code>javassist.runtime</code> package. - -<p><br> - -<a name="before"> -<h3>4.1 Inserting source text at the beginning/end of a method body</h3> - -<p><code>CtMethod</code> and <code>CtConstructor</code> provide -methods <code>insertBefore()</code>, <code>insertAfter()</code>, and -<code>addCatch()</code>. They are used for inserting a code fragment -into the body of an existing method. The users can specify those code -fragments with <em>source text</em> written in Java. -Javassist includes a simple Java compiler for processing source -text. It receives source text -written in Java and compiles it into Java bytecode, which will be -<em>inlined</em> into a method body. - -<p> -Inserting a code fragment at the position specified by a line number -is also possible -(if the line number table is contained in the class file). -<code>insertAt()</code> in <code>CtMethod</code> and -<code>CtConstructor</code> takes source text and a line number in the source -file of the original class definition. -It compiles the source text and inserts the compiled code at the line number. - -<p>The methods <code>insertBefore()</code>, <code>insertAfter()</code>, -<code>addCatch()</code>, and <code>insertAt()</code> -receive a <code>String</code> object representing -a statement or a block. A statement is a single control structure like -<code>if</code> and <code>while</code> or an expression ending with -a semi colon (<code>;</code>). A block is a set of -statements surrounded with braces <code>{}</code>. -Hence each of the following lines is an example of valid statement or block: - -<ul><pre>System.out.println("Hello"); -{ System.out.println("Hello"); } -if (i < 0) { i = -i; } -</pre></ul> - -<p>The statement and the block can refer to fields and methods. -They can also refer to the parameters -to the method that they are inserted into -if that method was compiled with the -g option -(to include a local variable attribute in the class file). -Otherwise, they must access the method parameters through the special -variables <code>$0</code>, <code>$1</code>, <code>$2</code>, ... described -below. -<em>Accessing local variables declared in the method is not allowed</em> -although declaring a new local variable in the block is allowed. -However, <code>insertAt()</code> allows the statement and the block -to access local variables -if these variables are available at the specified line number -and the target method was compiled with the -g option. - - -<!-- -<p><center><table border=8 cellspacing=0 bordercolor="#cfcfcf"> -<tr><td bgcolor="#cfcfcf"> -<b>Tip:</b> -<br>    Local variables are not accessible.   -</td></tr> -</table></center> ---> - -<p>The <code>String</code> object passed to the methods -<code>insertBefore()</code>, <code>insertAfter()</code>, -<code>addCatch()</code>, and <code>insertAt()</code> are compiled by -the compiler included in Javassist. -Since the compiler supports language extensions, -several identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> -<tr> -<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td> -<td>Actual parameters</td> -</tr> - -<tr> -<td><code>$args</code></td> -<td>An array of parameters. -The type of <code>$args</code> is <code>Object[]</code>. -</td> -</tr> - -<tr> -<td><code>$$</code></td> -<td rowspan=2>All actual parameters.<br> -For example, <code>m($$)</code> is equivalent to -<code>m($1,$2,</code>...<code>)</code></td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$cflow(</code>...<code>)</code></td> -<td><code>cflow</code> variable</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>The result type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td>The resulting value</td> -</tr> - -<tr> -<td><code>$sig</code></td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types. -</td> -</tr> - -<tr> -<td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr> -<td><code>$class</code></td> -<td>A <code>java.lang.Class</code> object representing -the class currently edited.</td> -</tr> - -</table> -</ul> - -<h4>$0, $1, $2, ...</h4> - -<p>The parameters passed to the target method -are accessible with -<code>$0</code>, <code>$1</code>, <code>$2</code>, ... instead of -the original parameter names. -<code>$1</code> represents the -first parameter, <code>$2</code> represents the second parameter, and -so on. The types of those variables are identical to the parameter -types. -<code>$0</code> is -equivalent to <code>this</code>. If the method is static, -<code>$0</code> is not available. - -<p>These variables are used as following. Suppose that a class -<code>Point</code>: - -<pre><ul>class Point { - int x, y; - void move(int dx, int dy) { x += dx; y += dy; } -} -</ul></pre> - -<p>To print the values of <code>dx</code> and <code>dy</code> -whenever the method <code>move()</code> is called, execute this -program: - -<ul><pre>ClassPool pool = ClassPool.getDefault(); -CtClass cc = pool.get("Point"); -CtMethod m = cc.getDeclaredMethod("move"); -m.insertBefore("{ System.out.println($1); System.out.println($2); }"); -cc.writeFile(); -</pre></ul> - -<p>Note that the source text passed to <code>insertBefore()</code> is -surrounded with braces <code>{}</code>. -<code>insertBefore()</code> accepts only a single statement or a block -surrounded with braces. - -<p>The definition of the class <code>Point</code> after the -modification is like this: - -<pre><ul>class Point { - int x, y; - void move(int dx, int dy) { - { System.out.println(dx); System.out.println(dy); } - x += dx; y += dy; - } -} -</ul></pre> - -<p><code>$1</code> and <code>$2</code> are replaced with -<code>dx</code> and <code>dy</code>, respectively. - -<p><code>$1</code>, <code>$2</code>, <code>$3</code> ... are -updatable. If a new value is assigend to one of those variables, -then the value of the parameter represented by that variable is -also updated. - - -<h4>$args</h4> - -<p>The variable <code>$args</code> represents an array of all the -parameters. The type of that variable is an array of class -<code>Object</code>. If a parameter type is a primitive type such as -<code>int</code>, then the parameter value is converted into a wrapper -object such as <code>java.lang.Integer</code> to store in -<code>$args</code>. Thus, <code>$args[0]</code> is equivalent to -<code>$1</code> unless the type of the first parameter is a primitive -type. Note that <code>$args[0]</code> is not equivalent to -<code>$0</code>; <code>$0</code> represents <code>this</code>. - -<p>If an array of <code>Object</code> is assigned to -<code>$args</code>, then each element of that array is -assigned to each parameter. If a parameter type is a primitive -type, the type of the corresponding element must be a wrapper type. -The value is converted from the wrapper type to the primitive type -before it is assigned to the parameter. - -<h4>$$</h4> - -<p>The variable <code>$$</code> is abbreviation of a list of -all the parameters separated by commas. -For example, if the number of the parameters -to method <code>move()</code> is three, then - -<ul><pre>move($$)</pre></ul> - -<p>is equivalent to this: - -<ul><pre>move($1, $2, $3)</pre></ul> - -<p>If <code>move()</code> does not take any parameters, -then <code>move($$)</code> is -equivalent to <code>move()</code>. - -<p><code>$$</code> can be used with another method. -If you write an expression: - -<ul><pre>exMove($$, context)</pre></ul> - -<p>then this expression is equivalent to: - -<ul><pre>exMove($1, $2, $3, context)</pre></ul> - -<p>Note that <code>$$</code> enables generic notation of method call -with respect to the number of parameters. -It is typically used with <code>$proceed</code> shown later. - -<h4>$cflow</h4> - -<p><code>$cflow</code> means "control flow". -This read-only variable returns the depth of the recursive calls -to a specific method. - -<p>Suppose that the method shown below is represented by a -<code>CtMethod</code> object <code>cm</code>: - -<ul><pre>int fact(int n) { - if (n <= 1) - return n; - else - return n * fact(n - 1); -}</pre></ul> - -<p>To use <code>$cflow</code>, first declare that <code>$cflow</code> -is used for monitoring calls to the method <code>fact()</code>: - -<ul><pre>CtMethod cm = ...; -cm.useCflow("fact");</pre></ul> - -<p>The parameter to <code>useCflow()</code> is the identifier of the -declared <code>$cflow</code> variable. Any valid Java name can be -used as the identifier. Since the identifier can also include -<code>.</code> (dot), for example, <code>"my.Test.fact"</code> -is a valid identifier. - -<p>Then, <code>$cflow(fact)</code> represents the depth of the -recursive calls to the method specified by <code>cm</code>. The value -of <code>$cflow(fact)</code> is 0 (zero) when the method is -first called whereas it is 1 when the method is recursively called -within the method. For example, - -<ul><pre> -cm.insertBefore("if ($cflow(fact) == 0)" - + " System.out.println(\"fact \" + $1);"); -</pre></ul> - -<p>translates the method <code>fact()</code> so that it shows the -parameter. Since the value of <code>$cflow(fact)</code> is checked, -the method <code>fact()</code> does not show the parameter if it is -recursively called within <code>fact()</code>. - -<p>The value of <code>$cflow</code> is the number of stack frames -associated with the specified method <code>cm</code> -under the current topmost -stack frame for the current thread. <code>$cflow</code> is also -accessible within a method different from the specified method -<code>cm</code>. - -<h4>$r</h4> - -<p><code>$r</code> represents the result type (return type) of the method. -It must be used as the cast type in a cast expression. -For example, this is a typical use: - -<ul><pre>Object result = ... ; -$_ = ($r)result;</pre></ul> - -<p>If the result type is a primitive type, then <code>($r)</code> -follows special semantics. First, if the operand type of the cast -expression is a primitive type, <code>($r)</code> works as a normal -cast operator to the result type. -On the other hand, if the operand type is a wrapper type, -<code>($r)</code> converts from the wrapper type to the result type. -For example, if the result type is <code>int</code>, then -<code>($r)</code> converts from <code>java.lang.Integer</code> to -<code>int</code>. - -<p>If the result type is <code>void</code>, then -<code>($r)</code> does not convert a type; it does nothing. -However, if the operand is a call to a <code>void</code> method, -then <code>($r)</code> results in <code>null</code>. For example, -if the result type is <code>void</code> and -<code>foo()</code> is a <code>void</code> method, then - -<ul><pre>$_ = ($r)foo();</pre></ul> - -<p>is a valid statement. - -<p>The cast operator <code>($r)</code> is also useful in a -<code>return</code> statement. Even if the result type is -<code>void</code>, the following <code>return</code> statement is valid: - -<ul><pre>return ($r)result;</pre></ul> - -<p>Here, <code>result</code> is some local variable. -Since <code>($r)</code> is specified, the resulting value is -discarded. -This <code>return</code> statement is regarded as the equivalent -of the <code>return</code> statement without a resulting value: - -<ul><pre>return;</pre></ul> - -<h4>$w</h4> - -<p><code>$w</code> represents a wrapper type. -It must be used as the cast type in a cast expression. -<code>($w)</code> converts from a primitive type to the corresponding -wrapper type. - -The following code is an example: - -<ul><pre>Integer i = ($w)5;</pre></ul> - -<p>The selected wrapper type depends on the type of the expression -following <code>($w)</code>. If the type of the expression is -<code>double</code>, then the wrapper type is <code>java.lang.Double</code>. - -<p>If the type of the expression following <code>($w)</code> is not -a primitive type, then <code>($w)</code> does nothing. - -<h4>$_</h4> - -<p><code>insertAfter()</code> in <code>CtMethod</code> and -<code>CtConstructor</code> inserts the -compiled code at the end of the method. In the statement given to -<code>insertAfter()</code>, not only the variables shown above such as -<code>$0</code>, <code>$1</code>, ... but also <code>$_</code> is -available. - -<p>The variable <code>$_</code> represents the resulting value of the -method. The type of that variable is the type of the result type (the -return type) of the method. If the result type is <code>void</code>, -then the type of <code>$_</code> is <code>Object</code> and the value -of <code>$_</code> is <code>null</code>. - -<p>Although the compiled code inserted by <code>insertAfter()</code> -is executed just before the control normally returns from the method, -it can be also executed when an exception is thrown from the method. -To execute it when an exception is thrown, the second parameter -<code>asFinally</code> to <code>insertAfter()</code> must be -<code>true</code>. - -<p>If an exception is thrown, the compiled code inserted by -<code>insertAfter()</code> is executed as a <code>finally</code> -clause. The value of <code>$_</code> is <code>0</code> or -<code>null</code> in the compiled code. After the execution of the -compiled code terminates, the exception originally thrown is re-thrown -to the caller. Note that the value of <code>$_</code> is never thrown -to the caller; it is rather discarded. - -<h4>$sig</h4> - -<p>The value of <code>$sig</code> is an array of -<code>java.lang.Class</code> objects that represent the formal -parameter types in declaration order. - -<h4>$type</h4> - -<p>The value of <code>$type</code> is an <code>java.lang.Class</code> -object representing the formal type of the result value. This -variable is available only in <code>insertAfter()</code> in -<code>CtMethod</code> and <code>CtConstructor</code>. - -<h4>$class</h4> - -<p>The value of <code>$class</code> is an <code>java.lang.Class</code> -object representing the class in which the edited method is declared. -This represents the type of <code>$0</code>. - -<h4>addCatch()</h4> - -<p><code>addCatch()</code> inserts a code fragment into a method body -so that the code fragment is executed when the method body throws -an exception and the control returns to the caller. In the source -text representing the inserted code fragment, the exception value -is referred to with the special variable <code>$e</code>. - -<p>For example, this program: - -<ul><pre> -CtMethod m = ...; -CtClass etype = ClassPool.getDefault().get("java.io.IOException"); -m.addCatch("{ System.out.println($e); throw $e; }", etype); -</pre></ul> - -<p>translates the method body represented by <code>m</code> into -something like this: - -<ul><pre> -try { - <font face="serif"><em>the original method body</em></font> -} -catch (java.io.IOException e) { - System.out.println(e); - throw e; -} -</pre></ul> - -<p>Note that the inserted code fragment must end with a -<code>throw</code> or <code>return</code> statement. - -<p><br> - -<a name="alter"> -<h3>4.2 Altering a method body</h3> - -<p><code>CtMethod</code> and <code>CtConstructor</code> provide -<code>setBody()</code> for substituting a whole -method body. They compile the given source text into Java bytecode -and substitutes it for the original method body. If the given source -text is <code>null</code>, the substituted body includes only a -<code>return</code> statement, which returns zero or null unless the -result type is <code>void</code>. - -<p>In the source text given to <code>setBody()</code>, the identifiers -starting with <code>$</code> have special meaning - -<ul><table border=0> -<tr> -<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td> -<td>Actual parameters</td> -</tr> - -<tr> -<td><code>$args</code></td> -<td>An array of parameters. -The type of <code>$args</code> is <code>Object[]</code>. -</td> -</tr> - -<tr> -<td><code>$$</code></td> -<td>All actual parameters.<br> -</tr> - -<tr> -<td><code>$cflow(</code>...<code>)</code></td> -<td><code>cflow</code> variable</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>The result type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression.</td> -</tr> - -<tr> -<td><code>$sig</code></td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types. -</td> -</tr> - -<tr> -<td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr> -<td><code>$class</code></td> -<td rowspan=2>A <code>java.lang.Class</code> object representing -the class that declares the method<br> -currently edited (the type of $0).</td> -</tr> - -<tr><td> </td></tr> - -</table> -</ul> - -Note that <code>$_</code> is not available. - -<h4>Substituting source text for an existing expression</h4> - -<p>Javassist allows modifying only an expression included in a method body. -<code>javassist.expr.ExprEditor</code> is a class -for replacing an expression in a method body. -The users can define a subclass of <code>ExprEditor</code> -to specify how an expression is modified. - -<p>To run an <code>ExprEditor</code> object, the users must -call <code>instrument()</code> in <code>CtMethod</code> or -<code>CtClass</code>. - -For example, - -<ul><pre> -CtMethod cm = ... ; -cm.instrument( - new ExprEditor() { - public void edit(MethodCall m) - throws CannotCompileException - { - if (m.getClassName().equals("Point") - && m.getMethodName().equals("move")) - m.replace("{ $1 = 0; $_ = $proceed($$); }"); - } - }); -</pre></ul> - -<p>searches the method body represented by <code>cm</code> and -replaces all calls to <code>move()</code> in class <code>Point</code> -with a block: - -<ul><pre>{ $1 = 0; $_ = $proceed($$); } -</pre></ul> - -<p>so that the first parameter to <code>move()</code> is always 0. -Note that the substituted code is not an expression but -a statement or a block. - -<p>The method <code>instrument()</code> searches a method body. -If it finds an expression such as a method call, field access, and object -creation, then it calls <code>edit()</code> on the given -<code>ExprEditor</code> object. The parameter to <code>edit()</code> -is an object representing the found expression. The <code>edit()</code> -method can inspect and replace the expression through that object. - -<p>Calling <code>replace()</code> on the parameter to <code>edit()</code> -substitutes the given statement or block for the expression. If the given -block is an empty block, that is, if <code>replace("{}")</code> -is executed, then the expression is removed from the method body. - -If you want to insert a statement (or a block) before/after the -expression, a block like the following should be passed to -<code>replace()</code>: - -<ul><pre> -{ <em>before-statements;</em> - $_ = $proceed($$); - <em>after-statements;</em> } -</pre></ul> - -<p>whichever the expression is either a method call, field access, -object creation, or others. The second statement could be: - -<ul><pre>$_ = $proceed();</pre></ul> - -<p>if the expression is read access, or - -<ul><pre>$proceed($$);</pre></ul> - -<p>if the expression is write access. - -<p>Local variables available in the target expression is -also available in the source text passed to <code>replace()</code> -if the method searched by <code>instrument()</code> was compiled -with the -g option (the class file includes a local variable -attribute). - -<h4>javassist.expr.MethodCall</h4> - -<p>A <code>MethodCall</code> object represents a method call. -The method <code>replace()</code> in -<code>MethodCall</code> substitutes a statement or -a block for the method call. -It receives source text representing the substitued statement or -block, in which the identifiers starting with <code>$</code> -have special meaning as in the source text passed to -<code>insertBefore()</code>. - -<ul><table border=0> -<tr> -<td><code>$0</code></td> -<td rowspan=3> -The target object of the method call.<br> -This is not equivalent to <code>this</code>, which represents -the caller-side <code>this</code> object.<br> -<code>$0</code> is <code>null</code> if the method is static. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The parameters of the method call. -</td> -</tr> - -<tr><td> -<code>$_</code></td> -<td>The resulting value of the method call.</td> -</tr> - -<tr><td><code>$r</code></td> -<td>The result type of the method call.</td> -</tr> - -<tr><td><code>$class</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class declaring the method. -</td> -</tr> - -<tr><td><code>$sig</code>    </td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types.</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the formal result type.</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of the method originally called -in the expression.</td> -</tr> - -</table> -</ul> - -<p>Here the method call means the one represented by the -<code>MethodCall</code> object. - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>Unless the result type of the method call is <code>void</code>, -a value must be assigned to -<code>$_</code> in the source text and the type of <code>$_</code> -is the result type. -If the result type is <code>void</code>, the type of <code>$_</code> -is <code>Object</code> and the value assigned to <code>$_</code> -is ignored. - -<p><code>$proceed</code> is not a <code>String</code> value but special -syntax. It must be followed by an argument list surrounded by parentheses -<code>( )</code>. - -<h4>javassist.expr.FieldAccess</h4> - -<p>A <code>FieldAccess</code> object represents field access. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if field access is found. -The method <code>replace()</code> in -<code>FieldAccess</code> receives -source text representing the substitued statement or -block for the field access. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> -<tr> -<td><code>$0</code></td> -<td rowspan=3> -The object containing the field accessed by the expression. -This is not equivalent to <code>this</code>.<br> -<code>this</code> represents the object that the method including the -expression is invoked on.<br> -<code>$0</code> is <code>null</code> if the field is static. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$1</code></td> -<td rowspan=2> -The value that would be stored in the field -if the expression is write access. -<br>Otherwise, <code>$1</code> is not available. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the field access -if the expression is read access. -<br>Otherwise, the value stored in <code>$_</code> is discarded. -</td> -</tr> - -<tr><td> </td></tr> -<tr> -<td><code>$r</code></td> -<td rowspan=2> -The type of the field if the expression is read access. -<br>Otherwise, <code>$r</code> is <code>void</code>. -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td><code>$class</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class declaring the field. -</td></tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the field type.</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -field access. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>If the expression is read access, a value must be assigned to -<code>$_</code> in the source text. The type of <code>$_</code> -is the type of the field. - -<h4>javassist.expr.NewExpr</h4> - -<p>A <code>NewExpr</code> object represents object creation -with the <code>new</code> operator (not including array creation). -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if object creation is found. -The method <code>replace()</code> in -<code>NewExpr</code> receives -source text representing the substitued statement or -block for the object creation. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The parameters to the constructor. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the object creation. -<br>A newly created object must be stored in this variable. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td> -The type of the created object. -</td> -</tr> - -<tr><td><code>$sig</code>    </td> -<td>An array of <code>java.lang.Class</code> objects representing -the formal parameter types.</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class of the created object. -</td></tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -object creation. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.NewArray</h4> - -<p>A <code>NewArray</code> object represents array creation -with the <code>new</code> operator. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if array creation is found. -The method <code>replace()</code> in -<code>NewArray</code> receives -source text representing the substitued statement or -block for the array creation. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code>, <code>$2</code>, ...    </td> -<td> -The size of each dimension. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the array creation. -<br>A newly created array must be stored in this variable. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td> -The type of the created array. -</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td>A <code>java.lang.Class</code> object representing -the class of the created array. -</td></tr> - -<tr><td><code>$proceed</code>    </td> -<td>The name of a virtual method executing the original -array creation. -.</td> -</tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<p>For example, if the array creation is the following expression, - -<ul><pre> -String[][] s = new String[3][4]; -</pre></ul> - -then the value of $1 and $2 are 3 and 4, respectively. $3 is not available. - -<p>If the array creation is the following expression, - -<ul><pre> -String[][] s = new String[3][]; -</pre></ul> - -then the value of $1 is 3 but $2 is not available. - -<h4>javassist.expr.Instanceof</h4> - -<p>A <code>Instanceof</code> object represents an <code>instanceof</code> -expression. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if an instanceof expression is found. -The method <code>replace()</code> in -<code>Instanceof</code> receives -source text representing the substitued statement or -block for the expression. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code></td> -<td> -The value on the left hand side of the original -<code>instanceof</code> operator. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td> -The resulting value of the expression. -The type of <code>$_</code> is <code>boolean</code>. -</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td> -The type on the right hand side of the <code>instanceof</code> operator. -</td> -</tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the type on the right hand side of the <code>instanceof</code> operator. -</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td rowspan=4>The name of a virtual method executing the original -<code>instanceof</code> expression. -<br>It takes one parameter (the type is <code>java.lang.Object</code>) -and returns true -<br>if the parameter value is an instance of the type on the right -hand side of -<br>the original <code>instanceof</code> operator. -Otherwise, it returns false. -</td> -</tr> - -<tr><td> </td></tr> -<tr><td> </td></tr> -<tr><td> </td></tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.Cast</h4> - -<p>A <code>Cast</code> object represents an expression for -explicit type casting. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if explicit type casting is found. -The method <code>replace()</code> in -<code>Cast</code> receives -source text representing the substitued statement or -block for the expression. - -<p> -In the source text, the identifiers starting with <code>$</code> -have special meaning: - -<ul><table border=0> - -<tr> -<td><code>$0</code></td> -<td> -<code>null</code>. -</td> -</tr> - -<tr> -<td><code>$1</code></td> -<td> -The value the type of which is explicitly cast. -</td> -</tr> - -<tr> -<td><code>$_</code></td> -<td rowspan=2> -The resulting value of the expression. -The type of <code>$_</code> is the same as the type -<br>after the explicit casting, that is, the type surrounded -by <code>( )</code>. -</td> -</tr> - -<tr><td> </td></tr> - -<tr> -<td><code>$r</code></td> -<td>the type after the explicit casting, or the type surrounded -by <code>( )</code>. -</td> -</tr> - -<tr><td><code>$type</code></td> -<td>A <code>java.lang.Class</code> object representing -the same type as <code>$r</code>. -</td> -</tr> - -<tr><td><code>$proceed</code>    </td> -<td rowspan=3>The name of a virtual method executing the original -type casting. -<br>It takes one parameter of the type <code>java.lang.Object</code> -and returns it after -<br>the explicit type casting specified by the original expression. - -</td> -</tr> - -<tr><td> </td></tr> - -<tr><td> </td></tr> - -</table> -</ul> - -<p>The other identifiers such as <code>$w</code>, -<code>$args</code> and <code>$$</code> -are also available. - -<h4>javassist.expr.Handler</h4> - -<p>A <code>Handler</code> object represents a <code>catch</code> -clause of <code>try-catch</code> statement. -The method <code>edit()</code> in <code>ExprEditor</code> -receives this object if a <code>catch</code> is found. -The method <code>insertBefore()</code> in -<code>Handler</code> compiles the received -source text and inserts it at the beginning of the <code>catch</code> clause. - -<p> -In the source text, the identifiers starting with <code>$</code> -have meaning: - -<ul><table border=0> - -<tr> -<td><code>$1</code></td> -<td> -The exception object caught by the <code>catch</code> clause. -</td> -</tr> - -<tr> -<td><code>$r</code></td> -<td>the type of the exception caught by the <code>catch</code> clause. -It is used in a cast expression. -</td> -</tr> - -<tr> -<td><code>$w</code></td> -<td>The wrapper type. It is used in a cast expression. -</td> -</tr> - -<tr><td><code>$type</code>    </td> -<td rowspan=2> -A <code>java.lang.Class</code> object representing -<br>the type of the exception caught by the <code>catch</code> clause. -</td> -</tr> - -<tr><td> </td></tr> - -</table> -</ul> - -<p>If a new exception object is assigned to <code>$1</code>, -it is passed to the original <code>catch</code> clause as the caught -exception. - -<p><br> - -<a name="add"> -<h3>4.3 Adding a new method or field</h3> - -<h4>Adding a method</h4> - -<p>Javassist allows the users to create a new method and constructor -from scratch. <code>CtNewMethod</code> -and <code>CtNewConstructor</code> provide several factory methods, -which are static methods for creating <code>CtMethod</code> or -<code>CtConstructor</code> objects. -Especially, <code>make()</code> creates -a <code>CtMethod</code> or <code>CtConstructor</code> object -from the given source text. - -<p>For example, this program: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtMethod m = CtNewMethod.make( - "public int xmove(int dx) { x += dx; }", - point); -point.addMethod(m); -</pre></ul> - -<p>adds a public method <code>xmove()</code> to class <code>Point</code>. -In this example, <code>x</code> is a <code>int</code> field in -the class <code>Point</code>. - -<p>The source text passed to <code>make()</code> can include the -identifiers starting with <code>$</code> except <code>$_</code> -as in <code>setBody()</code>. -It can also include -<code>$proceed</code> if the target object and the target method name -are also given to <code>make()</code>. For example, - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtMethod m = CtNewMethod.make( - "public int ymove(int dy) { $proceed(0, dy); }", - point, "this", "move"); -</pre></ul> - -<p>this program creates a method <code>ymove()</code> defined below: - -<ul><pre> -public int ymove(int dy) { this.move(0, dy); } -</pre></ul> - -<p>Note that <code>$proceed</code> has been replaced with -<code>this.move</code>. - -<p>Javassist provides another way to add a new method. -You can first create an abstract method and later give it a method body: - -<ul><pre> -CtClass cc = ... ; -CtMethod m = new CtMethod(CtClass.intType, "move", - new CtClass[] { CtClass.intType }, cc); -cc.addMethod(m); -m.setBody("{ x += $1; }"); -cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT); -</pre></ul> - -<p>Since Javassist makes a class abstract if an abstract method is -added to the class, you have to explicitly change the class back to a -non-abstract one after calling <code>setBody()</code>. - - -<h4>Mutual recursive methods</h4> - -<p>Javassist cannot compile a method if it calls another method that -has not been added to a class. (Javassist can compile a method that -calls itself recursively.) To add mutual recursive methods to a class, -you need a trick shown below. Suppose that you want to add methods -<code>m()</code> and <code>n()</code> to a class represented -by <code>cc</code>: - -<ul><pre> -CtClass cc = ... ; -CtMethod m = CtNewMethod.make("public abstract int m(int i);", cc); -CtMethod n = CtNewMethod.make("public abstract int n(int i);", cc); -cc.addMethod(m); -cc.addMethod(n); -m.setBody("{ return ($1 <= 0) ? 1 : (n($1 - 1) * $1); }"); -n.setBody("{ return m($1); }"); -cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT); -</pre></ul> - -<p>You must first make two abstract methods and add them to the class. -Then you can give the method bodies to these methods even if the method -bodies include method calls to each other. Finally you must change the -class to a not-abstract class since <code>addMethod()</code> automatically -changes a class into an abstract one if an abstract method is added. - -<h4>Adding a field</h4> - -<p>Javassist also allows the users to create a new field. - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = new CtField(CtClass.intType, "z", point); -point.addField(f); -</pre></ul> - -<p>This program adds a field named <code>z</code> to class -<code>Point</code>. - -<p>If the initial value of the added field must be specified, -the program shown above must be modified into: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = new CtField(CtClass.intType, "z", point); -point.addField(f, "0"); <em>// initial value is 0.</em> -</pre></ul> - -<p>Now, the method <code>addField()</code> receives the second parameter, -which is the source text representing an expression computing the initial -value. This source text can be any Java expression if the result type -of the expression matches the type of the field. Note that an expression -does not end with a semi colon (<code>;</code>). - -<p>Furthermore, the above code can be rewritten into the following -simple code: - -<ul><pre> -CtClass point = ClassPool.getDefault().get("Point"); -CtField f = CtField.make("public int z = 0;", point); -point.addField(f); -</pre></ul> - - -<p><br> - -<a name="runtime"> -<h3>4.4 Runtime support classes</h3> - -<p>In most cases, a class modified by Javassist does not require -Javassist to run. However, some kinds of bytecode generated by the -Javassist compiler need runtime support classes, which are in the -<code>javassist.runtime</code> package (for details, please read -the API reference of that package). Note that the -<code>javassist.runtime</code> package is the only package that -classes modified by Javassist may need for running. The other -Javassist classes are never used at runtime of the modified classes. - -<p><br> - -<a name="limit"> -<h3>4.5 Limitations</h3> - -<p>In the current implementation, the Java compiler included in Javassist -has several limitations with respect to the language that the compiler can -accept. Those limitations are: - -<p><li>All the class names must be fully qualified (they must include -package names). This is because the compiler does not support -<code>import</code> -declarations. However, the <code>java.lang</code> package is an -exception; for example, the compiler accepts <code>Object</code> as -well as <code>java.lang.Object</code>. - -<p><li>Array initializers, a comma-separated list of expressions -enclosed by braces <code>{</code> and <code>}</code>, are not -supported. - -<p><li>Inner classes or anonymous classes are not supported. - -<p><li>Labeled <code>continue</code> and <code>break</code> statements -are not supported. - -<p><li>The <code>finally</code> clause following -<code>try</code> and <code>catch</code> clauses is not supported. - -<p><li>The compiler does not correctly implement the Java method dispatch -algorithm. The compiler may confuse if methods defined in a class -have the same name but take different parameter lists. - -<p><li>The users are recommended to use <code>#</code> as the separator -between a class name and a static method or field name. -For example, in regular Java, - -<ul><pre>javassist.CtClass.intType.getName()</pre></ul> - -<p>calls a method <code>getName()</code> on -the object indicated by the static field <code>intType</code> -in <code>javassist.CtClass</code>. In Javassist, the users can -write the expression shown above but they are recommended to -write: - -<ul><pre>javassist.CtClass#intType.getName()</pre></ul> - -<p>so that the compiler can quickly parse the expression. -</ul> - -<p><br> - -<a href="tutorial.html">Previous page</a> - <a href="tutorial3.html">Next page</a> - -<hr> -Java(TM) is a trademark of Sun Microsystems, Inc.<br> -Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved. -</body> -</html> +<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Javassist Tutorial</title>
+ <link rel="stylesheet" type="text/css" href="brown.css">
+</head>
+
+<body>
+
+<div align="right">Getting Started with Javassist</div>
+
+<div align="left"><a href="tutorial.html">Previous page</a></div>
+<div align="right"><a href="tutorial3.html">Next page</a></div>
+
+<p>
+<a href="#intro">4. Introspection and customization</a>
+<ul>
+<li><a href="#before">Inserting source text at the beginning/end of a method body</a>
+<br><li><a href="#alter">Altering a method body</a>
+<br><li><a href="#add">Adding a new method or field</a>
+<br><li><a href="#runtime">Runtime support classes</a>
+<br><li><a href="#limit">Limitations</a>
+</ul>
+
+<p><br>
+
+<a name="intro">
+<h2>4. Introspection and customization</h2>
+
+<p><code>CtClass</code> provides methods for introspection. The
+introspective ability of Javassist is compatible with that of
+the Java reflection API. <code>CtClass</code> provides
+<code>getName()</code>, <code>getSuperclass()</code>,
+<code>getMethods()</code>, and so on.
+<code>CtClass</code> also provides methods for modifying a class
+definition. It allows to add a new field, constructor, and method.
+Instrumenting a method body is also possible.
+
+<p>
+Methods are represented by <code>CtMethod</code> objects.
+<code>CtMethod</code> provides several methods for modifying
+the definition of the method. Note that if a method is inherited
+from a super class, then
+the same <code>CtMethod</code> object
+that represents the inherited method represents the method declared
+in that super class.
+A <code>CtMethod</code> object corresponds to every method declaration.
+
+<p>
+For example, if class <code>Point</code> declares method <code>move()</code>
+and a subclass <code>ColorPoint</code> of <code>Point</code> does
+not override <code>move()</code>, the two <code>move()</code> methods
+declared in <code>Point</code> and inherited in <code>ColorPoint</code>
+are represented by the identical <code>CtMethod</code> object.
+If the method definition represented by this
+<code>CtMethod</code> object is modified, the modification is
+reflected on both the methods.
+If you want to modify only the <code>move()</code> method in
+<code>ColorPoint</code>, you first have to add to <code>ColorPoint</code>
+a copy of the <code>CtMethod</code> object representing <code>move()</code>
+in <code>Point</code>. A copy of the the <code>CtMethod</code> object
+can be obtained by <code>CtNewMethod.copy()</code>.
+
+
+<p><hr width="40%">
+
+<ul>
+Javassist does not allow to remove a method or field, but it allows
+to change the name. So if a method is not necessary any more, it should be
+renamed and changed to be a private method by calling
+<code>setName()</code>
+and <code>setModifiers()</code> declared in <code>CtMethod</code>.
+
+<p>Javassist does not allow to add an extra parameter to an existing
+method, either. Instead of doing that, a new method receiving the
+extra parameter as well as the other parameters should be added to the
+same class. For example, if you want to add an extra <code>int</code>
+parameter <code>newZ</code> to a method:
+
+<ul><pre>void move(int newX, int newY) { x = newX; y = newY; }</pre></ul>
+
+<p>in a <code>Point</code> class, then you should add the following
+method to the <code>Point</code> class:
+
+<ul><pre>void move(int newX, int newY, int newZ) {
+ // do what you want with newZ.
+ move(newX, newY);
+}</pre></ul>
+
+</ul>
+
+<p><hr width="40%">
+
+<p>Javassist also provides low-level API for directly editing a raw
+class file. For example, <code>getClassFile()</code> in
+<code>CtClass</code> returns a <code>ClassFile</code> object
+representing a raw class file. <code>getMethodInfo()</code> in
+<code>CtMethod</code> returns a <code>MethodInfo</code> object
+representing a <code>method_info</code> structure included in a class
+file. The low-level API uses the vocabulary from the Java Virtual
+machine specification. The users must have the knowledge about class
+files and bytecode. For more details, the users should see the
+<code>javassist.bytecode</code> package.
+
+<p>The class files modified by Javassist requires the
+<code>javassist.runtime</code> package for runtime support
+only if some special identifiers starting with <code>$</code>
+are used. Those special identifiers are described below.
+The class files modified without those special identifiers
+do not need the <code>javassist.runtime</code> package or any
+other Javassist packages at runtime.
+For more details, see the API documentation
+of the <code>javassist.runtime</code> package.
+
+<p><br>
+
+<a name="before">
+<h3>4.1 Inserting source text at the beginning/end of a method body</h3>
+
+<p><code>CtMethod</code> and <code>CtConstructor</code> provide
+methods <code>insertBefore()</code>, <code>insertAfter()</code>, and
+<code>addCatch()</code>. They are used for inserting a code fragment
+into the body of an existing method. The users can specify those code
+fragments with <em>source text</em> written in Java.
+Javassist includes a simple Java compiler for processing source
+text. It receives source text
+written in Java and compiles it into Java bytecode, which will be
+<em>inlined</em> into a method body.
+
+<p>
+Inserting a code fragment at the position specified by a line number
+is also possible
+(if the line number table is contained in the class file).
+<code>insertAt()</code> in <code>CtMethod</code> and
+<code>CtConstructor</code> takes source text and a line number in the source
+file of the original class definition.
+It compiles the source text and inserts the compiled code at the line number.
+
+<p>The methods <code>insertBefore()</code>, <code>insertAfter()</code>,
+<code>addCatch()</code>, and <code>insertAt()</code>
+receive a <code>String</code> object representing
+a statement or a block. A statement is a single control structure like
+<code>if</code> and <code>while</code> or an expression ending with
+a semi colon (<code>;</code>). A block is a set of
+statements surrounded with braces <code>{}</code>.
+Hence each of the following lines is an example of valid statement or block:
+
+<ul><pre>System.out.println("Hello");
+{ System.out.println("Hello"); }
+if (i < 0) { i = -i; }
+</pre></ul>
+
+<p>The statement and the block can refer to fields and methods.
+They can also refer to the parameters
+to the method that they are inserted into
+if that method was compiled with the -g option
+(to include a local variable attribute in the class file).
+Otherwise, they must access the method parameters through the special
+variables <code>$0</code>, <code>$1</code>, <code>$2</code>, ... described
+below.
+<em>Accessing local variables declared in the method is not allowed</em>
+although declaring a new local variable in the block is allowed.
+However, <code>insertAt()</code> allows the statement and the block
+to access local variables
+if these variables are available at the specified line number
+and the target method was compiled with the -g option.
+
+
+<!--
+<p><center><table border=8 cellspacing=0 bordercolor="#cfcfcf">
+<tr><td bgcolor="#cfcfcf">
+<b>Tip:</b>
+<br>    Local variables are not accessible.  
+</td></tr>
+</table></center>
+-->
+
+<p>The <code>String</code> object passed to the methods
+<code>insertBefore()</code>, <code>insertAfter()</code>,
+<code>addCatch()</code>, and <code>insertAt()</code> are compiled by
+the compiler included in Javassist.
+Since the compiler supports language extensions,
+several identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+<tr>
+<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td>
+<td>Actual parameters</td>
+</tr>
+
+<tr>
+<td><code>$args</code></td>
+<td>An array of parameters.
+The type of <code>$args</code> is <code>Object[]</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$$</code></td>
+<td rowspan=2>All actual parameters.<br>
+For example, <code>m($$)</code> is equivalent to
+<code>m($1,$2,</code>...<code>)</code></td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$cflow(</code>...<code>)</code></td>
+<td><code>cflow</code> variable</td>
+</tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>The result type. It is used in a cast expression.</td>
+</tr>
+
+<tr>
+<td><code>$w</code></td>
+<td>The wrapper type. It is used in a cast expression.</td>
+</tr>
+
+<tr>
+<td><code>$_</code></td>
+<td>The resulting value</td>
+</tr>
+
+<tr>
+<td><code>$sig</code></td>
+<td>An array of <code>java.lang.Class</code> objects representing
+the formal parameter types.
+</td>
+</tr>
+
+<tr>
+<td><code>$type</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the formal result type.</td>
+</tr>
+
+<tr>
+<td><code>$class</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the class currently edited.</td>
+</tr>
+
+</table>
+</ul>
+
+<h4>$0, $1, $2, ...</h4>
+
+<p>The parameters passed to the target method
+are accessible with
+<code>$0</code>, <code>$1</code>, <code>$2</code>, ... instead of
+the original parameter names.
+<code>$1</code> represents the
+first parameter, <code>$2</code> represents the second parameter, and
+so on. The types of those variables are identical to the parameter
+types.
+<code>$0</code> is
+equivalent to <code>this</code>. If the method is static,
+<code>$0</code> is not available.
+
+<p>These variables are used as following. Suppose that a class
+<code>Point</code>:
+
+<pre><ul>class Point {
+ int x, y;
+ void move(int dx, int dy) { x += dx; y += dy; }
+}
+</ul></pre>
+
+<p>To print the values of <code>dx</code> and <code>dy</code>
+whenever the method <code>move()</code> is called, execute this
+program:
+
+<ul><pre>ClassPool pool = ClassPool.getDefault();
+CtClass cc = pool.get("Point");
+CtMethod m = cc.getDeclaredMethod("move");
+m.insertBefore("{ System.out.println($1); System.out.println($2); }");
+cc.writeFile();
+</pre></ul>
+
+<p>Note that the source text passed to <code>insertBefore()</code> is
+surrounded with braces <code>{}</code>.
+<code>insertBefore()</code> accepts only a single statement or a block
+surrounded with braces.
+
+<p>The definition of the class <code>Point</code> after the
+modification is like this:
+
+<pre><ul>class Point {
+ int x, y;
+ void move(int dx, int dy) {
+ { System.out.println(dx); System.out.println(dy); }
+ x += dx; y += dy;
+ }
+}
+</ul></pre>
+
+<p><code>$1</code> and <code>$2</code> are replaced with
+<code>dx</code> and <code>dy</code>, respectively.
+
+<p><code>$1</code>, <code>$2</code>, <code>$3</code> ... are
+updatable. If a new value is assigend to one of those variables,
+then the value of the parameter represented by that variable is
+also updated.
+
+
+<h4>$args</h4>
+
+<p>The variable <code>$args</code> represents an array of all the
+parameters. The type of that variable is an array of class
+<code>Object</code>. If a parameter type is a primitive type such as
+<code>int</code>, then the parameter value is converted into a wrapper
+object such as <code>java.lang.Integer</code> to store in
+<code>$args</code>. Thus, <code>$args[0]</code> is equivalent to
+<code>$1</code> unless the type of the first parameter is a primitive
+type. Note that <code>$args[0]</code> is not equivalent to
+<code>$0</code>; <code>$0</code> represents <code>this</code>.
+
+<p>If an array of <code>Object</code> is assigned to
+<code>$args</code>, then each element of that array is
+assigned to each parameter. If a parameter type is a primitive
+type, the type of the corresponding element must be a wrapper type.
+The value is converted from the wrapper type to the primitive type
+before it is assigned to the parameter.
+
+<h4>$$</h4>
+
+<p>The variable <code>$$</code> is abbreviation of a list of
+all the parameters separated by commas.
+For example, if the number of the parameters
+to method <code>move()</code> is three, then
+
+<ul><pre>move($$)</pre></ul>
+
+<p>is equivalent to this:
+
+<ul><pre>move($1, $2, $3)</pre></ul>
+
+<p>If <code>move()</code> does not take any parameters,
+then <code>move($$)</code> is
+equivalent to <code>move()</code>.
+
+<p><code>$$</code> can be used with another method.
+If you write an expression:
+
+<ul><pre>exMove($$, context)</pre></ul>
+
+<p>then this expression is equivalent to:
+
+<ul><pre>exMove($1, $2, $3, context)</pre></ul>
+
+<p>Note that <code>$$</code> enables generic notation of method call
+with respect to the number of parameters.
+It is typically used with <code>$proceed</code> shown later.
+
+<h4>$cflow</h4>
+
+<p><code>$cflow</code> means "control flow".
+This read-only variable returns the depth of the recursive calls
+to a specific method.
+
+<p>Suppose that the method shown below is represented by a
+<code>CtMethod</code> object <code>cm</code>:
+
+<ul><pre>int fact(int n) {
+ if (n <= 1)
+ return n;
+ else
+ return n * fact(n - 1);
+}</pre></ul>
+
+<p>To use <code>$cflow</code>, first declare that <code>$cflow</code>
+is used for monitoring calls to the method <code>fact()</code>:
+
+<ul><pre>CtMethod cm = ...;
+cm.useCflow("fact");</pre></ul>
+
+<p>The parameter to <code>useCflow()</code> is the identifier of the
+declared <code>$cflow</code> variable. Any valid Java name can be
+used as the identifier. Since the identifier can also include
+<code>.</code> (dot), for example, <code>"my.Test.fact"</code>
+is a valid identifier.
+
+<p>Then, <code>$cflow(fact)</code> represents the depth of the
+recursive calls to the method specified by <code>cm</code>. The value
+of <code>$cflow(fact)</code> is 0 (zero) when the method is
+first called whereas it is 1 when the method is recursively called
+within the method. For example,
+
+<ul><pre>
+cm.insertBefore("if ($cflow(fact) == 0)"
+ + " System.out.println(\"fact \" + $1);");
+</pre></ul>
+
+<p>translates the method <code>fact()</code> so that it shows the
+parameter. Since the value of <code>$cflow(fact)</code> is checked,
+the method <code>fact()</code> does not show the parameter if it is
+recursively called within <code>fact()</code>.
+
+<p>The value of <code>$cflow</code> is the number of stack frames
+associated with the specified method <code>cm</code>
+under the current topmost
+stack frame for the current thread. <code>$cflow</code> is also
+accessible within a method different from the specified method
+<code>cm</code>.
+
+<h4>$r</h4>
+
+<p><code>$r</code> represents the result type (return type) of the method.
+It must be used as the cast type in a cast expression.
+For example, this is a typical use:
+
+<ul><pre>Object result = ... ;
+$_ = ($r)result;</pre></ul>
+
+<p>If the result type is a primitive type, then <code>($r)</code>
+follows special semantics. First, if the operand type of the cast
+expression is a primitive type, <code>($r)</code> works as a normal
+cast operator to the result type.
+On the other hand, if the operand type is a wrapper type,
+<code>($r)</code> converts from the wrapper type to the result type.
+For example, if the result type is <code>int</code>, then
+<code>($r)</code> converts from <code>java.lang.Integer</code> to
+<code>int</code>.
+
+<p>If the result type is <code>void</code>, then
+<code>($r)</code> does not convert a type; it does nothing.
+However, if the operand is a call to a <code>void</code> method,
+then <code>($r)</code> results in <code>null</code>. For example,
+if the result type is <code>void</code> and
+<code>foo()</code> is a <code>void</code> method, then
+
+<ul><pre>$_ = ($r)foo();</pre></ul>
+
+<p>is a valid statement.
+
+<p>The cast operator <code>($r)</code> is also useful in a
+<code>return</code> statement. Even if the result type is
+<code>void</code>, the following <code>return</code> statement is valid:
+
+<ul><pre>return ($r)result;</pre></ul>
+
+<p>Here, <code>result</code> is some local variable.
+Since <code>($r)</code> is specified, the resulting value is
+discarded.
+This <code>return</code> statement is regarded as the equivalent
+of the <code>return</code> statement without a resulting value:
+
+<ul><pre>return;</pre></ul>
+
+<h4>$w</h4>
+
+<p><code>$w</code> represents a wrapper type.
+It must be used as the cast type in a cast expression.
+<code>($w)</code> converts from a primitive type to the corresponding
+wrapper type.
+
+The following code is an example:
+
+<ul><pre>Integer i = ($w)5;</pre></ul>
+
+<p>The selected wrapper type depends on the type of the expression
+following <code>($w)</code>. If the type of the expression is
+<code>double</code>, then the wrapper type is <code>java.lang.Double</code>.
+
+<p>If the type of the expression following <code>($w)</code> is not
+a primitive type, then <code>($w)</code> does nothing.
+
+<h4>$_</h4>
+
+<p><code>insertAfter()</code> in <code>CtMethod</code> and
+<code>CtConstructor</code> inserts the
+compiled code at the end of the method. In the statement given to
+<code>insertAfter()</code>, not only the variables shown above such as
+<code>$0</code>, <code>$1</code>, ... but also <code>$_</code> is
+available.
+
+<p>The variable <code>$_</code> represents the resulting value of the
+method. The type of that variable is the type of the result type (the
+return type) of the method. If the result type is <code>void</code>,
+then the type of <code>$_</code> is <code>Object</code> and the value
+of <code>$_</code> is <code>null</code>.
+
+<p>Although the compiled code inserted by <code>insertAfter()</code>
+is executed just before the control normally returns from the method,
+it can be also executed when an exception is thrown from the method.
+To execute it when an exception is thrown, the second parameter
+<code>asFinally</code> to <code>insertAfter()</code> must be
+<code>true</code>.
+
+<p>If an exception is thrown, the compiled code inserted by
+<code>insertAfter()</code> is executed as a <code>finally</code>
+clause. The value of <code>$_</code> is <code>0</code> or
+<code>null</code> in the compiled code. After the execution of the
+compiled code terminates, the exception originally thrown is re-thrown
+to the caller. Note that the value of <code>$_</code> is never thrown
+to the caller; it is rather discarded.
+
+<h4>$sig</h4>
+
+<p>The value of <code>$sig</code> is an array of
+<code>java.lang.Class</code> objects that represent the formal
+parameter types in declaration order.
+
+<h4>$type</h4>
+
+<p>The value of <code>$type</code> is an <code>java.lang.Class</code>
+object representing the formal type of the result value. This
+variable is available only in <code>insertAfter()</code> in
+<code>CtMethod</code> and <code>CtConstructor</code>.
+
+<h4>$class</h4>
+
+<p>The value of <code>$class</code> is an <code>java.lang.Class</code>
+object representing the class in which the edited method is declared.
+This represents the type of <code>$0</code>.
+
+<h4>addCatch()</h4>
+
+<p><code>addCatch()</code> inserts a code fragment into a method body
+so that the code fragment is executed when the method body throws
+an exception and the control returns to the caller. In the source
+text representing the inserted code fragment, the exception value
+is referred to with the special variable <code>$e</code>.
+
+<p>For example, this program:
+
+<ul><pre>
+CtMethod m = ...;
+CtClass etype = ClassPool.getDefault().get("java.io.IOException");
+m.addCatch("{ System.out.println($e); throw $e; }", etype);
+</pre></ul>
+
+<p>translates the method body represented by <code>m</code> into
+something like this:
+
+<ul><pre>
+try {
+ <font face="serif"><em>the original method body</em></font>
+}
+catch (java.io.IOException e) {
+ System.out.println(e);
+ throw e;
+}
+</pre></ul>
+
+<p>Note that the inserted code fragment must end with a
+<code>throw</code> or <code>return</code> statement.
+
+<p><br>
+
+<a name="alter">
+<h3>4.2 Altering a method body</h3>
+
+<p><code>CtMethod</code> and <code>CtConstructor</code> provide
+<code>setBody()</code> for substituting a whole
+method body. They compile the given source text into Java bytecode
+and substitutes it for the original method body. If the given source
+text is <code>null</code>, the substituted body includes only a
+<code>return</code> statement, which returns zero or null unless the
+result type is <code>void</code>.
+
+<p>In the source text given to <code>setBody()</code>, the identifiers
+starting with <code>$</code> have special meaning
+
+<ul><table border=0>
+<tr>
+<td><code>$0</code>, <code>$1</code>, <code>$2</code>, ...    </td>
+<td>Actual parameters</td>
+</tr>
+
+<tr>
+<td><code>$args</code></td>
+<td>An array of parameters.
+The type of <code>$args</code> is <code>Object[]</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$$</code></td>
+<td>All actual parameters.<br>
+</tr>
+
+<tr>
+<td><code>$cflow(</code>...<code>)</code></td>
+<td><code>cflow</code> variable</td>
+</tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>The result type. It is used in a cast expression.</td>
+</tr>
+
+<tr>
+<td><code>$w</code></td>
+<td>The wrapper type. It is used in a cast expression.</td>
+</tr>
+
+<tr>
+<td><code>$sig</code></td>
+<td>An array of <code>java.lang.Class</code> objects representing
+the formal parameter types.
+</td>
+</tr>
+
+<tr>
+<td><code>$type</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the formal result type.</td>
+</tr>
+
+<tr>
+<td><code>$class</code></td>
+<td rowspan=2>A <code>java.lang.Class</code> object representing
+the class that declares the method<br>
+currently edited (the type of $0).</td>
+</tr>
+
+<tr><td> </td></tr>
+
+</table>
+</ul>
+
+Note that <code>$_</code> is not available.
+
+<h4>Substituting source text for an existing expression</h4>
+
+<p>Javassist allows modifying only an expression included in a method body.
+<code>javassist.expr.ExprEditor</code> is a class
+for replacing an expression in a method body.
+The users can define a subclass of <code>ExprEditor</code>
+to specify how an expression is modified.
+
+<p>To run an <code>ExprEditor</code> object, the users must
+call <code>instrument()</code> in <code>CtMethod</code> or
+<code>CtClass</code>.
+
+For example,
+
+<ul><pre>
+CtMethod cm = ... ;
+cm.instrument(
+ new ExprEditor() {
+ public void edit(MethodCall m)
+ throws CannotCompileException
+ {
+ if (m.getClassName().equals("Point")
+ && m.getMethodName().equals("move"))
+ m.replace("{ $1 = 0; $_ = $proceed($$); }");
+ }
+ });
+</pre></ul>
+
+<p>searches the method body represented by <code>cm</code> and
+replaces all calls to <code>move()</code> in class <code>Point</code>
+with a block:
+
+<ul><pre>{ $1 = 0; $_ = $proceed($$); }
+</pre></ul>
+
+<p>so that the first parameter to <code>move()</code> is always 0.
+Note that the substituted code is not an expression but
+a statement or a block.
+
+<p>The method <code>instrument()</code> searches a method body.
+If it finds an expression such as a method call, field access, and object
+creation, then it calls <code>edit()</code> on the given
+<code>ExprEditor</code> object. The parameter to <code>edit()</code>
+is an object representing the found expression. The <code>edit()</code>
+method can inspect and replace the expression through that object.
+
+<p>Calling <code>replace()</code> on the parameter to <code>edit()</code>
+substitutes the given statement or block for the expression. If the given
+block is an empty block, that is, if <code>replace("{}")</code>
+is executed, then the expression is removed from the method body.
+
+If you want to insert a statement (or a block) before/after the
+expression, a block like the following should be passed to
+<code>replace()</code>:
+
+<ul><pre>
+{ <em>before-statements;</em>
+ $_ = $proceed($$);
+ <em>after-statements;</em> }
+</pre></ul>
+
+<p>whichever the expression is either a method call, field access,
+object creation, or others. The second statement could be:
+
+<ul><pre>$_ = $proceed();</pre></ul>
+
+<p>if the expression is read access, or
+
+<ul><pre>$proceed($$);</pre></ul>
+
+<p>if the expression is write access.
+
+<p>Local variables available in the target expression is
+also available in the source text passed to <code>replace()</code>
+if the method searched by <code>instrument()</code> was compiled
+with the -g option (the class file includes a local variable
+attribute).
+
+<h4>javassist.expr.MethodCall</h4>
+
+<p>A <code>MethodCall</code> object represents a method call.
+The method <code>replace()</code> in
+<code>MethodCall</code> substitutes a statement or
+a block for the method call.
+It receives source text representing the substitued statement or
+block, in which the identifiers starting with <code>$</code>
+have special meaning as in the source text passed to
+<code>insertBefore()</code>.
+
+<ul><table border=0>
+<tr>
+<td><code>$0</code></td>
+<td rowspan=3>
+The target object of the method call.<br>
+This is not equivalent to <code>this</code>, which represents
+the caller-side <code>this</code> object.<br>
+<code>$0</code> is <code>null</code> if the method is static.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$1</code>, <code>$2</code>, ...    </td>
+<td>
+The parameters of the method call.
+</td>
+</tr>
+
+<tr><td>
+<code>$_</code></td>
+<td>The resulting value of the method call.</td>
+</tr>
+
+<tr><td><code>$r</code></td>
+<td>The result type of the method call.</td>
+</tr>
+
+<tr><td><code>$class</code>    </td>
+<td>A <code>java.lang.Class</code> object representing
+the class declaring the method.
+</td>
+</tr>
+
+<tr><td><code>$sig</code>    </td>
+<td>An array of <code>java.lang.Class</code> objects representing
+the formal parameter types.</td>
+</tr>
+
+<tr><td><code>$type</code>    </td>
+<td>A <code>java.lang.Class</code> object representing
+the formal result type.</td>
+</tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td>The name of the method originally called
+in the expression.</td>
+</tr>
+
+</table>
+</ul>
+
+<p>Here the method call means the one represented by the
+<code>MethodCall</code> object.
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<p>Unless the result type of the method call is <code>void</code>,
+a value must be assigned to
+<code>$_</code> in the source text and the type of <code>$_</code>
+is the result type.
+If the result type is <code>void</code>, the type of <code>$_</code>
+is <code>Object</code> and the value assigned to <code>$_</code>
+is ignored.
+
+<p><code>$proceed</code> is not a <code>String</code> value but special
+syntax. It must be followed by an argument list surrounded by parentheses
+<code>( )</code>.
+
+<h4>javassist.expr.FieldAccess</h4>
+
+<p>A <code>FieldAccess</code> object represents field access.
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if field access is found.
+The method <code>replace()</code> in
+<code>FieldAccess</code> receives
+source text representing the substitued statement or
+block for the field access.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+<tr>
+<td><code>$0</code></td>
+<td rowspan=3>
+The object containing the field accessed by the expression.
+This is not equivalent to <code>this</code>.<br>
+<code>this</code> represents the object that the method including the
+expression is invoked on.<br>
+<code>$0</code> is <code>null</code> if the field is static.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$1</code></td>
+<td rowspan=2>
+The value that would be stored in the field
+if the expression is write access.
+<br>Otherwise, <code>$1</code> is not available.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$_</code></td>
+<td rowspan=2>
+The resulting value of the field access
+if the expression is read access.
+<br>Otherwise, the value stored in <code>$_</code> is discarded.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+<tr>
+<td><code>$r</code></td>
+<td rowspan=2>
+The type of the field if the expression is read access.
+<br>Otherwise, <code>$r</code> is <code>void</code>.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr><td><code>$class</code>    </td>
+<td>A <code>java.lang.Class</code> object representing
+the class declaring the field.
+</td></tr>
+
+<tr><td><code>$type</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the field type.</td>
+</tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td>The name of a virtual method executing the original
+field access.
+.</td>
+</tr>
+
+</table>
+</ul>
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<p>If the expression is read access, a value must be assigned to
+<code>$_</code> in the source text. The type of <code>$_</code>
+is the type of the field.
+
+<h4>javassist.expr.NewExpr</h4>
+
+<p>A <code>NewExpr</code> object represents object creation
+with the <code>new</code> operator (not including array creation).
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if object creation is found.
+The method <code>replace()</code> in
+<code>NewExpr</code> receives
+source text representing the substitued statement or
+block for the object creation.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+
+<tr>
+<td><code>$0</code></td>
+<td>
+<code>null</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$1</code>, <code>$2</code>, ...    </td>
+<td>
+The parameters to the constructor.
+</td>
+</tr>
+
+<tr>
+<td><code>$_</code></td>
+<td rowspan=2>
+The resulting value of the object creation.
+<br>A newly created object must be stored in this variable.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>
+The type of the created object.
+</td>
+</tr>
+
+<tr><td><code>$sig</code>    </td>
+<td>An array of <code>java.lang.Class</code> objects representing
+the formal parameter types.</td>
+</tr>
+
+<tr><td><code>$type</code>    </td>
+<td>A <code>java.lang.Class</code> object representing
+the class of the created object.
+</td></tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td>The name of a virtual method executing the original
+object creation.
+.</td>
+</tr>
+
+</table>
+</ul>
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<h4>javassist.expr.NewArray</h4>
+
+<p>A <code>NewArray</code> object represents array creation
+with the <code>new</code> operator.
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if array creation is found.
+The method <code>replace()</code> in
+<code>NewArray</code> receives
+source text representing the substitued statement or
+block for the array creation.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+
+<tr>
+<td><code>$0</code></td>
+<td>
+<code>null</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$1</code>, <code>$2</code>, ...    </td>
+<td>
+The size of each dimension.
+</td>
+</tr>
+
+<tr>
+<td><code>$_</code></td>
+<td rowspan=2>
+The resulting value of the array creation.
+<br>A newly created array must be stored in this variable.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>
+The type of the created array.
+</td>
+</tr>
+
+<tr><td><code>$type</code>    </td>
+<td>A <code>java.lang.Class</code> object representing
+the class of the created array.
+</td></tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td>The name of a virtual method executing the original
+array creation.
+.</td>
+</tr>
+
+</table>
+</ul>
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<p>For example, if the array creation is the following expression,
+
+<ul><pre>
+String[][] s = new String[3][4];
+</pre></ul>
+
+then the value of $1 and $2 are 3 and 4, respectively. $3 is not available.
+
+<p>If the array creation is the following expression,
+
+<ul><pre>
+String[][] s = new String[3][];
+</pre></ul>
+
+then the value of $1 is 3 but $2 is not available.
+
+<h4>javassist.expr.Instanceof</h4>
+
+<p>A <code>Instanceof</code> object represents an <code>instanceof</code>
+expression.
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if an instanceof expression is found.
+The method <code>replace()</code> in
+<code>Instanceof</code> receives
+source text representing the substitued statement or
+block for the expression.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+
+<tr>
+<td><code>$0</code></td>
+<td>
+<code>null</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$1</code></td>
+<td>
+The value on the left hand side of the original
+<code>instanceof</code> operator.
+</td>
+</tr>
+
+<tr>
+<td><code>$_</code></td>
+<td>
+The resulting value of the expression.
+The type of <code>$_</code> is <code>boolean</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>
+The type on the right hand side of the <code>instanceof</code> operator.
+</td>
+</tr>
+
+<tr><td><code>$type</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the type on the right hand side of the <code>instanceof</code> operator.
+</td>
+</tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td rowspan=4>The name of a virtual method executing the original
+<code>instanceof</code> expression.
+<br>It takes one parameter (the type is <code>java.lang.Object</code>)
+and returns true
+<br>if the parameter value is an instance of the type on the right
+hand side of
+<br>the original <code>instanceof</code> operator.
+Otherwise, it returns false.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+<tr><td> </td></tr>
+<tr><td> </td></tr>
+
+</table>
+</ul>
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<h4>javassist.expr.Cast</h4>
+
+<p>A <code>Cast</code> object represents an expression for
+explicit type casting.
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if explicit type casting is found.
+The method <code>replace()</code> in
+<code>Cast</code> receives
+source text representing the substitued statement or
+block for the expression.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have special meaning:
+
+<ul><table border=0>
+
+<tr>
+<td><code>$0</code></td>
+<td>
+<code>null</code>.
+</td>
+</tr>
+
+<tr>
+<td><code>$1</code></td>
+<td>
+The value the type of which is explicitly cast.
+</td>
+</tr>
+
+<tr>
+<td><code>$_</code></td>
+<td rowspan=2>
+The resulting value of the expression.
+The type of <code>$_</code> is the same as the type
+<br>after the explicit casting, that is, the type surrounded
+by <code>( )</code>.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>the type after the explicit casting, or the type surrounded
+by <code>( )</code>.
+</td>
+</tr>
+
+<tr><td><code>$type</code></td>
+<td>A <code>java.lang.Class</code> object representing
+the same type as <code>$r</code>.
+</td>
+</tr>
+
+<tr><td><code>$proceed</code>    </td>
+<td rowspan=3>The name of a virtual method executing the original
+type casting.
+<br>It takes one parameter of the type <code>java.lang.Object</code>
+and returns it after
+<br>the explicit type casting specified by the original expression.
+
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+<tr><td> </td></tr>
+
+</table>
+</ul>
+
+<p>The other identifiers such as <code>$w</code>,
+<code>$args</code> and <code>$$</code>
+are also available.
+
+<h4>javassist.expr.Handler</h4>
+
+<p>A <code>Handler</code> object represents a <code>catch</code>
+clause of <code>try-catch</code> statement.
+The method <code>edit()</code> in <code>ExprEditor</code>
+receives this object if a <code>catch</code> is found.
+The method <code>insertBefore()</code> in
+<code>Handler</code> compiles the received
+source text and inserts it at the beginning of the <code>catch</code> clause.
+
+<p>
+In the source text, the identifiers starting with <code>$</code>
+have meaning:
+
+<ul><table border=0>
+
+<tr>
+<td><code>$1</code></td>
+<td>
+The exception object caught by the <code>catch</code> clause.
+</td>
+</tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>the type of the exception caught by the <code>catch</code> clause.
+It is used in a cast expression.
+</td>
+</tr>
+
+<tr>
+<td><code>$w</code></td>
+<td>The wrapper type. It is used in a cast expression.
+</td>
+</tr>
+
+<tr><td><code>$type</code>    </td>
+<td rowspan=2>
+A <code>java.lang.Class</code> object representing
+<br>the type of the exception caught by the <code>catch</code> clause.
+</td>
+</tr>
+
+<tr><td> </td></tr>
+
+</table>
+</ul>
+
+<p>If a new exception object is assigned to <code>$1</code>,
+it is passed to the original <code>catch</code> clause as the caught
+exception.
+
+<p><br>
+
+<a name="add">
+<h3>4.3 Adding a new method or field</h3>
+
+<h4>Adding a method</h4>
+
+<p>Javassist allows the users to create a new method and constructor
+from scratch. <code>CtNewMethod</code>
+and <code>CtNewConstructor</code> provide several factory methods,
+which are static methods for creating <code>CtMethod</code> or
+<code>CtConstructor</code> objects.
+Especially, <code>make()</code> creates
+a <code>CtMethod</code> or <code>CtConstructor</code> object
+from the given source text.
+
+<p>For example, this program:
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtMethod m = CtNewMethod.make(
+ "public int xmove(int dx) { x += dx; }",
+ point);
+point.addMethod(m);
+</pre></ul>
+
+<p>adds a public method <code>xmove()</code> to class <code>Point</code>.
+In this example, <code>x</code> is a <code>int</code> field in
+the class <code>Point</code>.
+
+<p>The source text passed to <code>make()</code> can include the
+identifiers starting with <code>$</code> except <code>$_</code>
+as in <code>setBody()</code>.
+It can also include
+<code>$proceed</code> if the target object and the target method name
+are also given to <code>make()</code>. For example,
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtMethod m = CtNewMethod.make(
+ "public int ymove(int dy) { $proceed(0, dy); }",
+ point, "this", "move");
+</pre></ul>
+
+<p>this program creates a method <code>ymove()</code> defined below:
+
+<ul><pre>
+public int ymove(int dy) { this.move(0, dy); }
+</pre></ul>
+
+<p>Note that <code>$proceed</code> has been replaced with
+<code>this.move</code>.
+
+<p>Javassist provides another way to add a new method.
+You can first create an abstract method and later give it a method body:
+
+<ul><pre>
+CtClass cc = ... ;
+CtMethod m = new CtMethod(CtClass.intType, "move",
+ new CtClass[] { CtClass.intType }, cc);
+cc.addMethod(m);
+m.setBody("{ x += $1; }");
+cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT);
+</pre></ul>
+
+<p>Since Javassist makes a class abstract if an abstract method is
+added to the class, you have to explicitly change the class back to a
+non-abstract one after calling <code>setBody()</code>.
+
+
+<h4>Mutual recursive methods</h4>
+
+<p>Javassist cannot compile a method if it calls another method that
+has not been added to a class. (Javassist can compile a method that
+calls itself recursively.) To add mutual recursive methods to a class,
+you need a trick shown below. Suppose that you want to add methods
+<code>m()</code> and <code>n()</code> to a class represented
+by <code>cc</code>:
+
+<ul><pre>
+CtClass cc = ... ;
+CtMethod m = CtNewMethod.make("public abstract int m(int i);", cc);
+CtMethod n = CtNewMethod.make("public abstract int n(int i);", cc);
+cc.addMethod(m);
+cc.addMethod(n);
+m.setBody("{ return ($1 <= 0) ? 1 : (n($1 - 1) * $1); }");
+n.setBody("{ return m($1); }");
+cc.setModifiers(cc.getModifiers() & ~Modifier.ABSTRACT);
+</pre></ul>
+
+<p>You must first make two abstract methods and add them to the class.
+Then you can give the method bodies to these methods even if the method
+bodies include method calls to each other. Finally you must change the
+class to a not-abstract class since <code>addMethod()</code> automatically
+changes a class into an abstract one if an abstract method is added.
+
+<h4>Adding a field</h4>
+
+<p>Javassist also allows the users to create a new field.
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtField f = new CtField(CtClass.intType, "z", point);
+point.addField(f);
+</pre></ul>
+
+<p>This program adds a field named <code>z</code> to class
+<code>Point</code>.
+
+<p>If the initial value of the added field must be specified,
+the program shown above must be modified into:
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtField f = new CtField(CtClass.intType, "z", point);
+point.addField(f, "0"); <em>// initial value is 0.</em>
+</pre></ul>
+
+<p>Now, the method <code>addField()</code> receives the second parameter,
+which is the source text representing an expression computing the initial
+value. This source text can be any Java expression if the result type
+of the expression matches the type of the field. Note that an expression
+does not end with a semi colon (<code>;</code>).
+
+<p>Furthermore, the above code can be rewritten into the following
+simple code:
+
+<ul><pre>
+CtClass point = ClassPool.getDefault().get("Point");
+CtField f = CtField.make("public int z = 0;", point);
+point.addField(f);
+</pre></ul>
+
+
+<p><br>
+
+<a name="runtime">
+<h3>4.4 Runtime support classes</h3>
+
+<p>In most cases, a class modified by Javassist does not require
+Javassist to run. However, some kinds of bytecode generated by the
+Javassist compiler need runtime support classes, which are in the
+<code>javassist.runtime</code> package (for details, please read
+the API reference of that package). Note that the
+<code>javassist.runtime</code> package is the only package that
+classes modified by Javassist may need for running. The other
+Javassist classes are never used at runtime of the modified classes.
+
+<p><br>
+
+<a name="limit">
+<h3>4.5 Limitations</h3>
+
+<p>In the current implementation, the Java compiler included in Javassist
+has several limitations with respect to the language that the compiler can
+accept. Those limitations are:
+
+<p><li>The new syntax introduced by J2SE 5.0 (including enums and generics)
+has not been supported. Annotations are supported only by the low level
+API of Javassist.
+See the <code>javassist.bytecode.annotation</code> package.
+
+<p><li>All the class names must be fully qualified (they must include
+package names). This is because the compiler does not support
+<code>import</code>
+declarations. However, the <code>java.lang</code> package is an
+exception; for example, the compiler accepts <code>Object</code> as
+well as <code>java.lang.Object</code>.
+
+<p><li>Array initializers, a comma-separated list of expressions
+enclosed by braces <code>{</code> and <code>}</code>, are not
+supported.
+
+<p><li>Inner classes or anonymous classes are not supported.
+
+<p><li>Labeled <code>continue</code> and <code>break</code> statements
+are not supported.
+
+<p><li>The compiler does not correctly implement the Java method dispatch
+algorithm. The compiler may confuse if methods defined in a class
+have the same name but take different parameter lists.
+
+<p>For example,
+
+<ul><pre>
+class A {}
+class B extends A {}
+class C extends C {}
+
+class X {
+ void foo(A a) { .. }
+ void foo(B b) { .. }
+}
+</pre></ul>
+
+<p>If the compiled expression is <code>x.foo(new C())</code>, where
+<code>x</code> is an instance of X, the compiler may produce a call
+to <code>foo(A)</code> although the compiler can correctly compile
+<code>foo((B)new C())</code>.
+
+<p><li>The users are recommended to use <code>#</code> as the separator
+between a class name and a static method or field name.
+For example, in regular Java,
+
+<ul><pre>javassist.CtClass.intType.getName()</pre></ul>
+
+<p>calls a method <code>getName()</code> on
+the object indicated by the static field <code>intType</code>
+in <code>javassist.CtClass</code>. In Javassist, the users can
+write the expression shown above but they are recommended to
+write:
+
+<ul><pre>javassist.CtClass#intType.getName()</pre></ul>
+
+<p>so that the compiler can quickly parse the expression.
+</ul>
+
+<p><br>
+
+<a href="tutorial.html">Previous page</a>
+ <a href="tutorial3.html">Next page</a>
+
+<hr>
+Java(TM) is a trademark of Sun Microsystems, Inc.<br>
+Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.
+</body>
+</html>
|