123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 |
- <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>
-
- <a name="intro">
- <h2>5. 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><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><br>
-
- <h3>5.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>The methods <code>insertBefore()</code>, <code>insertAfter()</code>, and
- <code>addCatch()</code> receives 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.
- However, they <em>cannot refer to local variables</em> declared in the
- method that they are inserted into.
- They can refer to the parameters
- to the method although they must use different names
- <code>$0</code>, <code>$1</code>, <code>$2</code>, ... described
- below. Declaring a local variable in the block is allowed.
-
- <!--
- <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>, and
- <code>addCatch()</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 methods <code>insertBefore()</code>,
- <code>insertAfter()</code>, and <code>addCatch()</code>
- 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.
-
- <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>
-
- <h3>5.2 Modifying 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>A <code>java.lang.Class</code> object representing
- the class currently edited.</td>
- </tr>
-
- </table>
- </ul>
-
- Note that <code>$_</code> is not available.
-
-
- <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.
-
- <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.
-
- In the source text, the identifiers starting with <code>$</code>
- have also 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.
- 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.
-
- In the source text, the identifiers starting with <code>$</code>
- have also 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>$class</code>    </td>
- <td>A <code>java.lang.Class</code> object representing
- the class 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>$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.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.
-
- In the source text, the identifiers starting with <code>$</code>
- have also 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.
-
- In the source text, the identifiers starting with <code>$</code>
- have also 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.
-
- In the source text, the identifiers starting with <code>$</code>
- have special 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>
-
- <h3>5.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><br>
-
- <h3>5.4 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 <code>.class</code> notation is not supported. Use the
- method <code>Class.forName()</code>.
- In regular
- Java, an expression <code>Point.class</code> means a <code>Class</code>
- object representing the <code>Point</code> class. This notation is
- not available.
-
- <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><code>switch</code> or <code>synchronized</code>
- statements are not supported yet.
-
- <p><li>Labeled <code>continue</code> and <code>break</code> statements
- are not supported.
-
- <p><li>The <code>finally</code> clause following
- <code>try</code> and <code>catch</code> clauses is not supported.
-
- <p><li>The compiler does not correctly implement the Java method dispatch
- algorithm. The compiler may confuse if methods defined in a class
- have the same name but take different parameter lists.
-
- <p><li>The users are recommended to use <code>#</code> as the separator
- between a class name and a static method or field name.
- For example, in regular Java,
-
- <ul><pre>javassist.CtClass.intType.getName()</pre></ul>
-
- <p>calls a method <code>getName()</code> on
- the object indicated by the static field <code>intType</code>
- in <code>javassist.CtClass</code>. In Javassist, the users can
- write the expression shown above but they are recommended to
- write:
-
- <ul><pre>javassist.CtClass#intType.getName()</pre></ul>
-
- <p>so that the compiler can quickly parse the expression.
- </ul>
-
- <p><br>
-
- <a href="tutorial.html">Previous page</a>
-
- <hr>
- Java(TM) is a trademark of Sun Microsystems, Inc.<br>
- Copyright (C) 2000-2003 by Shigeru Chiba, All rights reserved.
- </body>
- </html>
|