aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-08-02 18:50:41 +0000
committerchiba <chiba@30ef5769-5b8d-40dd-aea6-55b5d6557bb3>2004-08-02 18:50:41 +0000
commit3b946e08d56d6f0327ef5d501f9f2c5363e0f544 (patch)
tree9897b7bf5d2e34b26c27a6a5351fa8572ff800f9
parentf4a78cf275e5a1a8f81fed70d73f6273f6f9150f (diff)
downloadjavassist-3b946e08d56d6f0327ef5d501f9f2c5363e0f544.tar.gz
javassist-3b946e08d56d6f0327ef5d501f9f2c5363e0f544.zip
javassist.expr.NewArray has been implemented.
git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@120 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
-rw-r--r--Readme.html7
-rw-r--r--src/main/javassist/bytecode/Descriptor.java29
-rw-r--r--src/main/javassist/compiler/Javac.java8
-rw-r--r--src/main/javassist/compiler/JvstCodeGen.java16
-rw-r--r--src/main/javassist/expr/ExprEditor.java90
-rw-r--r--src/main/javassist/expr/NewArray.java281
-rw-r--r--tutorial/tutorial2.html117
7 files changed, 494 insertions, 54 deletions
diff --git a/Readme.html b/Readme.html
index b968d9d8..a1db7766 100644
--- a/Readme.html
+++ b/Readme.html
@@ -255,10 +255,13 @@ see javassist.Dump.
<h2>Changes</h2>
-<p>- version 3.0
+<p>- version 3.0 beta 3
<ul>
- <li>CtClass.toClass() has been reimplemented.
+ <li>CtClass.toClass() has been reimplemented. The behavior has been
+ changed.
+ <li>javassist.expr.NewArray has been implemented. It enables modifying
+ an expression for array creation.
</ul>
<p>- version 3.0 beta in May 18th, 2004.
diff --git a/src/main/javassist/bytecode/Descriptor.java b/src/main/javassist/bytecode/Descriptor.java
index 9c5b69c7..4a352aaf 100644
--- a/src/main/javassist/bytecode/Descriptor.java
+++ b/src/main/javassist/bytecode/Descriptor.java
@@ -512,6 +512,35 @@ public class Descriptor {
}
/**
+ * Computes the dimension of the array represented by the given
+ * descriptor. For example, if the descriptor is <code>"[[I"</code>,
+ * then this method returns 2.
+ *
+ * @param desc the descriptor.
+ * @return 0 if the descriptor does not represent an array type.
+ */
+ public static int arrayDimension(String desc) {
+ int dim = 0;
+ while (desc.charAt(dim) == '[')
+ ++dim;
+
+ return dim;
+ }
+
+ /**
+ * Returns the descriptor of the type of the array component.
+ * For example, if the given descriptor is
+ * <code>"[[Ljava/lang/String;"</code> and the given dimension is 2,
+ * then this method returns <code>"Ljava/lang/String;"</code>.
+ *
+ * @param desc the descriptor.
+ * @param dim the array dimension.
+ */
+ public static String toArrayComponent(String desc, int dim) {
+ return desc.substring(dim);
+ }
+
+ /**
* Computes the data size specified by the given descriptor.
* For example, if the descriptor is "D", this method returns 2.
*
diff --git a/src/main/javassist/compiler/Javac.java b/src/main/javassist/compiler/Javac.java
index 216d0198..67d0cef5 100644
--- a/src/main/javassist/compiler/Javac.java
+++ b/src/main/javassist/compiler/Javac.java
@@ -323,6 +323,7 @@ public class Javac {
* parameters. $args represents an array of all the parameters.
* It also makes $$ available as a parameter list of method call.
* $0 can represent a local variable other than THIS (variable 0).
+ * $class is also made available.
*
* <p>This must be called before calling <code>compileStmnt()</code> and
* <code>compileExpr()</code>. The correct value of
@@ -332,6 +333,8 @@ public class Javac {
* @param varNo the register number of $0 (use0 is true)
* or $1 (otherwise).
* @param target the type of $0 (it can be null if use0 is false).
+ * It is used as the name of the type represented
+ * by $class.
* @param isStatic true if the method in which the compiled bytecode
* is embedded is static.
*/
@@ -345,14 +348,17 @@ public class Javac {
/**
* Prepares to use cast $r, $w, $_, and $type.
+ * $type is made to represent the specified return type.
* It also enables to write a return statement with a return value
* for void method.
*
* <p>If the return type is void, ($r) does nothing.
* The type of $_ is java.lang.Object.
*
+ * @param type the return type.
* @param useResultVar true if $_ is used.
* @return -1 or the variable index assigned to $_.
+ * @see #recordType(CtClass)
*/
public int recordReturnType(CtClass type, boolean useResultVar)
throws CompileError
@@ -365,6 +371,8 @@ public class Javac {
/**
* Prepares to use $type. Note that recordReturnType() overwrites
* the value of $type.
+ *
+ * @param t the type represented by $type.
*/
public void recordType(CtClass t) {
gen.recordType(t);
diff --git a/src/main/javassist/compiler/JvstCodeGen.java b/src/main/javassist/compiler/JvstCodeGen.java
index 6c78f477..6800a9c8 100644
--- a/src/main/javassist/compiler/JvstCodeGen.java
+++ b/src/main/javassist/compiler/JvstCodeGen.java
@@ -458,7 +458,7 @@ public class JvstCodeGen extends MemberCodeGen {
}
/**
- * Makes method parameters $0, $1, ..., $args, and $$ available.
+ * Makes method parameters $0, $1, ..., $args, $$, and $class available.
* $0 is equivalent to THIS if the method is not static. Otherwise,
* if the method is static, then $0 is not available.
*/
@@ -472,15 +472,20 @@ public class JvstCodeGen extends MemberCodeGen {
}
/**
- * Makes method parameters $0, $1, ..., $args, and $$ available.
+ * Makes method parameters $0, $1, ..., $args, $$, and $class available.
* $0 is available only if use0 is true. It might not be equivalent
* to THIS.
*
- * @paaram use0 true if $0 is used.
+ * @param params the parameter types (the types of $1, $2, ..)
+ * @param prefix it must be "$" (the first letter of $0, $1, ...)
+ * @param paramVarName it must be "$args"
+ * @param paramsName it must be "$$"
+ * @param use0 true if $0 is used.
* @param paramBase the register number of $0 (use0 is true)
* or $1 (otherwise).
* @param target the class of $0. If use0 is false, target
- * can be null.
+ * can be null. The value of "target" is also used
+ * as the name of the type represented by $class.
* @param isStatic true if the method in which the compiled bytecode
* is embedded is static.
*/
@@ -499,7 +504,8 @@ public class JvstCodeGen extends MemberCodeGen {
paramVarBase = paramBase;
useParam0 = use0;
- param0Type = MemberResolver.jvmToJavaName(target);
+ if (target != null)
+ param0Type = MemberResolver.jvmToJavaName(target);
inStaticMethod = isStatic;
varNo = paramBase;
diff --git a/src/main/javassist/expr/ExprEditor.java b/src/main/javassist/expr/ExprEditor.java
index f4ef04eb..8f7cacb8 100644
--- a/src/main/javassist/expr/ExprEditor.java
+++ b/src/main/javassist/expr/ExprEditor.java
@@ -108,44 +108,57 @@ public class ExprEditor {
int pos = iterator.next();
int c = iterator.byteAt(pos);
- if (c == Opcode.INVOKESTATIC || c == Opcode.INVOKEINTERFACE
- || c == Opcode.INVOKEVIRTUAL) {
- expr = new MethodCall(pos, iterator, clazz, minfo);
- edit((MethodCall)expr);
- }
- else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC
- || c == Opcode.PUTFIELD || c == Opcode.PUTSTATIC) {
- expr = new FieldAccess(pos, iterator, clazz, minfo, c);
- edit((FieldAccess)expr);
- }
- else if (c == Opcode.NEW) {
- int index = iterator.u16bitAt(pos + 1);
- newList = new NewOp(newList, pos,
- cp.getClassInfo(index));
- }
- else if (c == Opcode.INVOKESPECIAL) {
- if (newList != null && cp.isConstructor(newList.type,
- iterator.u16bitAt(pos + 1)) > 0) {
- expr = new NewExpr(pos, iterator, clazz, minfo,
- newList.type, newList.pos);
- edit((NewExpr)expr);
- newList = newList.next;
- }
- else {
+ if (c < Opcode.GETSTATIC) // c < 178
+ /* skip */;
+ else if (c < Opcode.NEWARRAY) { // c < 188
+ if (c == Opcode.INVOKESTATIC
+ || c == Opcode.INVOKEINTERFACE
+ || c == Opcode.INVOKEVIRTUAL) {
expr = new MethodCall(pos, iterator, clazz, minfo);
- MethodCall mcall = (MethodCall)expr;
- if (!mcall.getMethodName().equals(
+ edit((MethodCall)expr);
+ }
+ else if (c == Opcode.GETFIELD || c == Opcode.GETSTATIC
+ || c == Opcode.PUTFIELD
+ || c == Opcode.PUTSTATIC) {
+ expr = new FieldAccess(pos, iterator, clazz, minfo, c);
+ edit((FieldAccess)expr);
+ }
+ else if (c == Opcode.NEW) {
+ int index = iterator.u16bitAt(pos + 1);
+ newList = new NewOp(newList, pos,
+ cp.getClassInfo(index));
+ }
+ else if (c == Opcode.INVOKESPECIAL) {
+ if (newList != null && cp.isConstructor(newList.type,
+ iterator.u16bitAt(pos + 1)) > 0) {
+ expr = new NewExpr(pos, iterator, clazz, minfo,
+ newList.type, newList.pos);
+ edit((NewExpr)expr);
+ newList = newList.next;
+ }
+ else {
+ expr = new MethodCall(pos, iterator, clazz, minfo);
+ MethodCall mcall = (MethodCall)expr;
+ if (!mcall.getMethodName().equals(
MethodInfo.nameInit))
- edit(mcall);
+ edit(mcall);
+ }
}
}
- else if (c == Opcode.INSTANCEOF) {
- expr = new Instanceof(pos, iterator, clazz, minfo);
- edit((Instanceof)expr);
- }
- else if (c == Opcode.CHECKCAST) {
- expr = new Cast(pos, iterator, clazz, minfo);
- edit((Cast)expr);
+ else { // c >= 188
+ if (c == Opcode.NEWARRAY || c == Opcode.ANEWARRAY
+ || c == Opcode.MULTIANEWARRAY) {
+ expr = new NewArray(pos, iterator, clazz, minfo, c);
+ edit((NewArray)expr);
+ }
+ else if (c == Opcode.INSTANCEOF) {
+ expr = new Instanceof(pos, iterator, clazz, minfo);
+ edit((Instanceof)expr);
+ }
+ else if (c == Opcode.CHECKCAST) {
+ expr = new Cast(pos, iterator, clazz, minfo);
+ edit((Cast)expr);
+ }
}
if (expr != null && expr.edited()) {
@@ -188,6 +201,15 @@ public class ExprEditor {
public void edit(NewExpr e) throws CannotCompileException {}
/**
+ * Edits an expression for array creation (overridable).
+ * The default implementation performs nothing.
+ *
+ * @param a the <tt>new</tt> expression for creating an array.
+ * @throws CannotCompileException
+ */
+ public void edit(NewArray a) throws CannotCompileException {}
+
+ /**
* Edits a method call (overridable).
* The default implementation performs nothing.
*/
diff --git a/src/main/javassist/expr/NewArray.java b/src/main/javassist/expr/NewArray.java
new file mode 100644
index 00000000..db34cf85
--- /dev/null
+++ b/src/main/javassist/expr/NewArray.java
@@ -0,0 +1,281 @@
+/*
+ * Javassist, a Java-bytecode translator toolkit.
+ * Copyright (C) 1999-2004 Shigeru Chiba. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. Alternatively, the contents of this file may be used under
+ * the terms of the GNU Lesser General Public License Version 2.1 or later.
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ */
+
+package javassist.expr;
+
+import javassist.*;
+import javassist.bytecode.*;
+import javassist.compiler.*;
+import javassist.compiler.ast.ASTList;
+
+/**
+ * Array creation.
+ *
+ * <p>This class does not provide methods for obtaining the initial
+ * values of array elements.
+ */
+public class NewArray extends Expr {
+ int opcode;
+
+ NewArray(int pos, CodeIterator i, CtClass declaring, MethodInfo m,
+ int op) {
+ super(pos, i, declaring, m);
+ opcode = op;
+ }
+
+ /**
+ * Returns the method or constructor containing the array creation
+ * represented by this object.
+ */
+ public CtBehavior where() { return super.where(); }
+
+ /**
+ * Returns the line number of the source line containing the
+ * array creation.
+ *
+ * @return -1 if this information is not available.
+ */
+ public int getLineNumber() {
+ return super.getLineNumber();
+ }
+
+ /**
+ * Returns the source file containing the array creation.
+ *
+ * @return null if this information is not available.
+ */
+ public String getFileName() {
+ return super.getFileName();
+ }
+
+ /**
+ * Returns the list of exceptions that the expression may throw.
+ * This list includes both the exceptions that the try-catch statements
+ * including the expression can catch and the exceptions that
+ * the throws declaration allows the method to throw.
+ */
+ public CtClass[] mayThrow() {
+ return super.mayThrow();
+ }
+
+ /**
+ * Returns the type of array components. If the created array is
+ * a two-dimensional array of <tt>int</tt>,
+ * the type returned by this method is
+ * not <tt>int[]</tt> but <tt>int</tt>.
+ */
+ public CtClass getComponentType() throws NotFoundException {
+ if (opcode == Opcode.NEWARRAY) {
+ int atype = iterator.byteAt(currentPos + 1);
+ return getPrimitiveType(atype);
+ }
+ else if (opcode == Opcode.ANEWARRAY
+ || opcode == Opcode.MULTIANEWARRAY) {
+ int index = iterator.u16bitAt(currentPos + 1);
+ String desc = getConstPool().getClassInfo(index);
+ int dim = Descriptor.arrayDimension(desc);
+ desc = Descriptor.toArrayComponent(desc, dim);
+ return Descriptor.toCtClass(desc, thisClass.getClassPool());
+ }
+ else
+ throw new RuntimeException("bad opcode: " + opcode);
+ }
+
+ CtClass getPrimitiveType(int atype) {
+ switch (atype) {
+ case Opcode.T_BOOLEAN :
+ return CtClass.booleanType;
+ case Opcode.T_CHAR :
+ return CtClass.charType;
+ case Opcode.T_FLOAT :
+ return CtClass.floatType;
+ case Opcode.T_DOUBLE :
+ return CtClass.doubleType;
+ case Opcode.T_BYTE :
+ return CtClass.byteType;
+ case Opcode.T_SHORT :
+ return CtClass.shortType;
+ case Opcode.T_INT :
+ return CtClass.intType;
+ case Opcode.T_LONG :
+ return CtClass.longType;
+ default :
+ throw new RuntimeException("bad atype: " + atype);
+ }
+ }
+
+ /**
+ * Returns the dimension of the created array.
+ */
+ public int getDimension() {
+ if (opcode == Opcode.NEWARRAY)
+ return 1;
+ else if (opcode == Opcode.ANEWARRAY
+ || opcode == Opcode.MULTIANEWARRAY) {
+ int index = iterator.u16bitAt(currentPos + 1);
+ String desc = getConstPool().getClassInfo(index);
+ return Descriptor.arrayDimension(desc)
+ + (opcode == Opcode.ANEWARRAY ? 1 : 0);
+ }
+ else
+ throw new RuntimeException("bad opcode: " + opcode);
+ }
+
+ /**
+ * Returns the number of dimensions of arrays to be created.
+ * If the opcode is multianewarray, this method returns the second
+ * operand. Otherwise, it returns 1.
+ */
+ public int getCreatedDimensions() {
+ if (opcode == Opcode.MULTIANEWARRAY)
+ return iterator.byteAt(currentPos + 3);
+ else
+ return 1;
+ }
+
+ /**
+ * Replaces the array creation with the bytecode derived from
+ * the given source text.
+ *
+ * <p>$0 is available even if the called method is static.
+ * If the field access is writing, $_ is available but the value
+ * of $_ is ignored.
+ *
+ * @param statement a Java statement.
+ */
+ public void replace(String statement) throws CannotCompileException {
+ try {
+ replace2(statement);
+ }
+ catch (CompileError e) { throw new CannotCompileException(e); }
+ catch (NotFoundException e) { throw new CannotCompileException(e); }
+ catch (BadBytecode e) {
+ throw new CannotCompileException("broken method");
+ }
+ }
+
+ private void replace2(String statement)
+ throws CompileError, NotFoundException, BadBytecode,
+ CannotCompileException
+ {
+ ConstPool constPool = getConstPool();
+ int pos = currentPos;
+ CtClass retType;
+ int codeLength;
+ int index = 0;
+ int dim = 1;
+ String desc;
+ if (opcode == Opcode.NEWARRAY) {
+ index = iterator.byteAt(currentPos + 1); // atype
+ CtPrimitiveType cpt = (CtPrimitiveType)getPrimitiveType(index);
+ desc = "[" + cpt.getDescriptor();
+ codeLength = 2;
+ }
+ else if (opcode == Opcode.ANEWARRAY) {
+ index = iterator.u16bitAt(pos + 1);
+ desc = constPool.getClassInfo(index);
+ if (desc.startsWith("["))
+ desc = "[" + desc;
+ else
+ desc = "[L" + desc + ";";
+
+ codeLength = 3;
+ }
+ else if (opcode == Opcode.MULTIANEWARRAY) {
+ index = iterator.u16bitAt(currentPos + 1);
+ desc = constPool.getClassInfo(index);
+ dim = iterator.byteAt(currentPos + 3);
+ codeLength = 4;
+ }
+ else
+ throw new RuntimeException("bad opcode: " + opcode);
+
+ retType = Descriptor.toCtClass(desc, thisClass.getClassPool());
+
+ Javac jc = new Javac(thisClass);
+ CodeAttribute ca = iterator.get();
+
+ CtClass[] params = new CtClass[dim];
+ for (int i = 0; i < dim; ++i)
+ params[i] = CtClass.intType;
+
+ int paramVar = ca.getMaxLocals();
+ jc.recordParams(javaLangObject, params,
+ true, paramVar, withinStatic());
+
+ /* Is $_ included in the source code?
+ */
+ checkResultValue(retType, statement);
+ int retVar = jc.recordReturnType(retType, true);
+ jc.recordProceed(new ProceedForArray(retType, opcode, index, dim));
+
+ Bytecode bytecode = jc.getBytecode();
+ storeStack(params, true, paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
+
+ bytecode.addOpcode(ACONST_NULL); // initialize $_
+ bytecode.addAstore(retVar);
+
+ jc.compileStmnt(statement);
+ bytecode.addAload(retVar);
+
+ replace0(pos, bytecode, codeLength);
+ }
+
+ /* <array type> $proceed(<dim> ..)
+ */
+ static class ProceedForArray implements ProceedHandler {
+ CtClass arrayType;
+ int opcode;
+ int index, dimension;
+
+ ProceedForArray(CtClass type, int op, int i, int dim) {
+ arrayType = type;
+ opcode = op;
+ index = i;
+ dimension = dim;
+ }
+
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ throws CompileError
+ {
+ int num = gen.getMethodArgsLength(args);
+ if (num != dimension)
+ throw new CompileError(Javac.proceedName
+ + "() with a wrong number of parameters");
+
+ gen.atMethodArgs(args, new int[num],
+ new int[num], new String[num]);
+ bytecode.addOpcode(opcode);
+ if (opcode == Opcode.ANEWARRAY)
+ bytecode.addIndex(index);
+ else if (opcode == Opcode.NEWARRAY)
+ bytecode.add(index);
+ else /* if (opcode == Opcode.MULTIANEWARRAY) */ {
+ bytecode.addIndex(index);
+ bytecode.add(dimension);
+ bytecode.growStack(1 - dimension);
+ }
+
+ gen.setType(arrayType);
+ }
+
+ public void setReturnType(JvstTypeChecker c, ASTList args)
+ throws CompileError
+ {
+ c.setType(arrayType);
+ }
+ }
+}
diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html
index 937c4427..50d24712 100644
--- a/tutorial/tutorial2.html
+++ b/tutorial/tutorial2.html
@@ -516,6 +516,7 @@ variable is available only in <code>insertAfter()</code> in
<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>
@@ -613,10 +614,13 @@ the formal result type.</td>
<tr>
<td><code>$class</code></td>
-<td>A <code>java.lang.Class</code> object representing
-the class currently edited.</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>&nbsp</td></tr>
+
</table>
</ul>
@@ -795,8 +799,9 @@ The method <code>replace()</code> in
source text representing the substitued statement or
block for the field access.
+<p>
In the source text, the identifiers starting with <code>$</code>
-have also special meaning:
+have special meaning:
<ul><table border=0>
<tr>
@@ -875,7 +880,7 @@ 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.
+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
@@ -883,8 +888,9 @@ The method <code>replace()</code> in
source text representing the substitued statement or
block for the object creation.
+<p>
In the source text, the identifiers starting with <code>$</code>
-have also special meaning:
+have special meaning:
<ul><table border=0>
@@ -919,16 +925,16 @@ The type of the created object.
</td>
</tr>
-<tr><td><code>$class</code> &nbsp &nbsp</td>
-<td>A <code>java.lang.Class</code> object representing
-the class of the created object.
-</td></tr>
-
<tr><td><code>$sig</code> &nbsp &nbsp</td>
<td>An array of <code>java.lang.Class</code> objects representing
the formal parameter types.</td>
</tr>
+<tr><td><code>$type</code> &nbsp &nbsp</td>
+<td>A <code>java.lang.Class</code> object representing
+the class of the created object.
+</td></tr>
+
<tr><td><code>$proceed</code> &nbsp &nbsp</td>
<td>The name of a virtual method executing the original
object creation.
@@ -942,6 +948,88 @@ object creation.
<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>, ... &nbsp &nbsp</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>&nbsp</td></tr>
+
+<tr>
+<td><code>$r</code></td>
+<td>
+The type of the created array.
+</td>
+</tr>
+
+<tr><td><code>$type</code> &nbsp &nbsp</td>
+<td>A <code>java.lang.Class</code> object representing
+the class of the created array.
+</td></tr>
+
+<tr><td><code>$proceed</code> &nbsp &nbsp</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>
@@ -953,8 +1041,9 @@ The method <code>replace()</code> in
source text representing the substitued statement or
block for the expression.
+<p>
In the source text, the identifiers starting with <code>$</code>
-have also special meaning:
+have special meaning:
<ul><table border=0>
@@ -1028,8 +1117,9 @@ The method <code>replace()</code> in
source text representing the substitued statement or
block for the expression.
+<p>
In the source text, the identifiers starting with <code>$</code>
-have also special meaning:
+have special meaning:
<ul><table border=0>
@@ -1103,8 +1193,9 @@ 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 special meaning:
+have meaning:
<ul><table border=0>