diff options
-rw-r--r-- | Readme.html | 3 | ||||
-rw-r--r-- | build.xml | 4 | ||||
-rw-r--r-- | src/main/javassist/ClassPool.java | 3 | ||||
-rw-r--r-- | src/main/javassist/CtClass.java | 12 | ||||
-rw-r--r-- | src/main/javassist/CtClassType.java | 26 | ||||
-rw-r--r-- | tutorial/tutorial2.html | 2928 |
6 files changed, 1506 insertions, 1470 deletions
diff --git a/Readme.html b/Readme.html index 910429cf..01cd0d15 100644 --- a/Readme.html +++ b/Readme.html @@ -577,7 +577,8 @@ Andreas Salathe, Dante Torres estrada, S. Pam, Nuno Santos, Denis Taye, Colin Sampaleanu, Robert Bialek, Asato Shimotaki, Howard Lewis Ship, Richard Jones, Marjan Sterjev, Bruce McDonald, Mark Brennan, Vlad Skarzhevskyy, -Brett Randall, Tsuyoshi Murakami, Nathan Meyers, and Yoshiyuki Usui +Brett Randall, Tsuyoshi Murakami, Nathan Meyers, Yoshiyuki Usui +Yutaka Sunaga, and Arjan van der Meer for their contributions. <p><br> @@ -6,7 +6,7 @@ <project name="javassist" default="jar" basedir="."> - <property name="dist-version" value="javassist-3.0RC1"/> + <property name="dist-version" value="javassist-3.0"/> <property environment="env"/> <property name="target.jar" value="javassist.jar"/> @@ -87,7 +87,7 @@ to ${build.classes.dir}.</echo> windowtitle="Javassist API"> <doctitle><![CDATA[<h1>Javassist</h1>]]></doctitle> <bottom><![CDATA[<i>Javassist, a Java-bytecode translator toolkit. -Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.</i>]]></bottom> +Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.</i>]]></bottom> </javadoc> </target> diff --git a/src/main/javassist/ClassPool.java b/src/main/javassist/ClassPool.java index 50143d6a..3e0ed6f5 100644 --- a/src/main/javassist/ClassPool.java +++ b/src/main/javassist/ClassPool.java @@ -248,6 +248,9 @@ public class ClassPool { throws NotFoundException { CtClass clazz = get0(orgName, false); + if (clazz == null) + throw new NotFoundException(orgName); + if (clazz instanceof CtClassType) ((CtClassType)clazz).setClassPool(this); diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java index 78b40150..d3de83c5 100644 --- a/src/main/javassist/CtClass.java +++ b/src/main/javassist/CtClass.java @@ -531,13 +531,23 @@ public abstract class CtClass { * If this class is a member class or interface of another class, * then the class enclosing this class is returned. * - * @return null if this class is a top-level class. + * @return null if this class is a top-level class or an anonymous class. */ public CtClass getDeclaringClass() throws NotFoundException { return null; } /** + * Returns the immediately enclosing class of this class. + * This method works only with JDK 1.5 or later. + * + * @return null if this class is a top-level class. + */ + public CtClass getEnclosingClass() throws NotFoundException { + return null; + } + + /** * Makes a new nested class. Making a nested class modifies the * data in this <code>CtClass</code>. * diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java index d567a9b9..2993a343 100644 --- a/src/main/javassist/CtClassType.java +++ b/src/main/javassist/CtClassType.java @@ -24,6 +24,7 @@ import javassist.bytecode.CodeAttribute; import javassist.bytecode.CodeIterator; import javassist.bytecode.ConstPool; import javassist.bytecode.Descriptor; +import javassist.bytecode.EnclosingMethodAttribute; import javassist.bytecode.FieldInfo; import javassist.bytecode.InnerClassesAttribute; import javassist.bytecode.MethodInfo; @@ -186,6 +187,10 @@ class CtClassType extends CtClass { fin = new BufferedInputStream(fin); classfile = new ClassFile(new DataInputStream(fin)); + if (!classfile.getName().equals(qualifiedName)) + throw new RuntimeException(classfile.getName() + " in " + + qualifiedName.replace('.', '/') + ".java"); + return classfile; } catch (NotFoundException e) { @@ -421,12 +426,29 @@ class CtClassType extends CtClass { String name = getName(); int n = ica.tableLength(); for (int i = 0; i < n; ++i) - if (name.equals(ica.innerClass(i))) - return classPool.get(ica.outerClass(i)); + if (name.equals(ica.innerClass(i))) { + String outName = ica.outerClass(i); + if (outName != null) + return classPool.get(outName); + } return null; } + public CtClass getEnclosingClass() throws NotFoundException { + CtClass enc = getDeclaringClass(); + if (enc == null) { + ClassFile cf = getClassFile2(); + EnclosingMethodAttribute ema + = (EnclosingMethodAttribute)cf.getAttribute( + EnclosingMethodAttribute.tag); + if (ema != null) + enc = classPool.get(ema.className()); + } + + return enc; + } + public CtClass makeNestedClass(String name, boolean isStatic) { if (!isStatic) throw new RuntimeException( diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html index d8d7381d..63d75ce0 100644 --- a/tutorial/tutorial2.html +++ b/tutorial/tutorial2.html @@ -1,1464 +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>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>
+<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> |