summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Readme.html2
-rw-r--r--src/main/javassist/CtBehavior.java11
-rw-r--r--src/main/javassist/CtClass.java2
-rw-r--r--src/main/javassist/compiler/Javac.java72
-rw-r--r--src/main/javassist/compiler/JvstCodeGen.java22
-rw-r--r--src/main/javassist/expr/Cast.java1
-rw-r--r--src/main/javassist/expr/FieldAccess.java1
-rw-r--r--src/main/javassist/expr/Instanceof.java1
-rw-r--r--src/main/javassist/expr/MethodCall.java1
-rw-r--r--src/main/javassist/expr/NewExpr.java1
-rw-r--r--tutorial/tutorial.html2
-rw-r--r--tutorial/tutorial2.html35
12 files changed, 119 insertions, 32 deletions
diff --git a/Readme.html b/Readme.html
index 7fad5788..3d688faa 100644
--- a/Readme.html
+++ b/Readme.html
@@ -253,6 +253,8 @@ see javassist.Dump.
<p>- version 2.7
<ul>
+ <li>Now local variables were made available in the source text passed to
+ CtBehavior.insertBefore(), MethodCall.replace(), etc.
<li>CtClass.main(), which prints the version number, has been added.
<li>ClassPool.SimpleLoader has been public.
<li>javassist.bytecode.DeprecatedAttribute has been added.
diff --git a/src/main/javassist/CtBehavior.java b/src/main/javassist/CtBehavior.java
index 52a13095..ea256482 100644
--- a/src/main/javassist/CtBehavior.java
+++ b/src/main/javassist/CtBehavior.java
@@ -352,8 +352,9 @@ public abstract class CtBehavior extends CtMember {
CodeIterator iterator = ca.iterator();
Javac jv = new Javac(declaringClass);
try {
- jv.recordParams(getParameterTypes(),
- Modifier.isStatic(getModifiers()));
+ int nvars = jv.recordParams(getParameterTypes(),
+ Modifier.isStatic(getModifiers()));
+ jv.recordParamNames(ca, nvars);
jv.compileStmnt(src);
Bytecode b = jv.getBytecode();
int stack = b.getMaxStack();
@@ -418,8 +419,9 @@ public abstract class CtBehavior extends CtMember {
b.setStackDepth(ca.getMaxStack() + 1);
Javac jv = new Javac(b, declaringClass);
try {
- jv.recordParams(getParameterTypes(),
- Modifier.isStatic(getModifiers()));
+ int nvars = jv.recordParams(getParameterTypes(),
+ Modifier.isStatic(getModifiers()));
+ jv.recordParamNames(ca, nvars);
CtClass rtype = getReturnType0();
int varNo = jv.recordReturnType(rtype, true);
@@ -750,6 +752,7 @@ public abstract class CtBehavior extends CtMember {
CodeIterator iterator = ca.iterator();
Javac jv = new Javac(declaringClass);
try {
+ jv.recordLocalVariables(ca, index);
jv.recordParams(getParameterTypes(),
Modifier.isStatic(getModifiers()));
jv.compileStmnt(src);
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index bded5c90..268c40f1 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -36,7 +36,7 @@ public abstract class CtClass {
/**
* The version number of this release.
*/
- public static final String version = "2.7 alpha 7";
+ public static final String version = "2.7 alpha 8";
/**
* Prints the version number and the copyright notice.
diff --git a/src/main/javassist/compiler/Javac.java b/src/main/javassist/compiler/Javac.java
index 4f83bda8..5e20e7e8 100644
--- a/src/main/javassist/compiler/Javac.java
+++ b/src/main/javassist/compiler/Javac.java
@@ -25,6 +25,8 @@ import javassist.CtConstructor;
import javassist.CannotCompileException;
import javassist.Modifier;
import javassist.bytecode.Bytecode;
+import javassist.bytecode.CodeAttribute;
+import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.Opcode;
import javassist.NotFoundException;
@@ -242,6 +244,66 @@ public class Javac {
}
/**
+ * Records local variables available at the specified program counter.
+ * If the LocalVariableAttribute is not available, this method does not
+ * record any local variable. It only returns false.
+ *
+ * @param pc program counter (&gt;= 0)
+ * @return false if the CodeAttribute does not include a
+ * LocalVariableAttribute.
+ */
+ public boolean recordLocalVariables(CodeAttribute ca, int pc)
+ throws CompileError
+ {
+ LocalVariableAttribute va
+ = (LocalVariableAttribute)
+ ca.getAttribute(LocalVariableAttribute.tag);
+ if (va == null)
+ return false;
+
+ int n = va.tableLength();
+ for (int i = 0; i < n; ++i) {
+ int start = va.startPc(i);
+ int len = va.codeLength(i);
+ if (start <= pc && pc < start + len)
+ gen.recordVariable(va.descriptor(i), va.variableName(i),
+ va.index(i), stable);
+ }
+
+ return true;
+ }
+
+ /**
+ * Records parameter names if the LocalVariableAttribute is available.
+ * It returns false unless the LocalVariableAttribute is available.
+ *
+ * @param numOfLocalVars the number of local variables used
+ * for storing the parameters.
+ * @return false if the CodeAttribute does not include a
+ * LocalVariableAttribute.
+ */
+ public boolean recordParamNames(CodeAttribute ca, int numOfLocalVars)
+ throws CompileError
+ {
+ LocalVariableAttribute va
+ = (LocalVariableAttribute)
+ ca.getAttribute(LocalVariableAttribute.tag);
+ if (va == null)
+ return false;
+
+ int n = va.tableLength();
+ for (int i = 0; i < n; ++i) {
+ int index = va.index(i);
+ if (index < numOfLocalVars)
+ gen.recordVariable(va.descriptor(i), va.variableName(i),
+ index, stable);
+ }
+
+ return true;
+ }
+
+
+ /**
* Makes variables $0 (this), $1, $2, ..., and $args represent method
* parameters. $args represents an array of all the parameters.
* It also makes $$ available as a parameter list of method call.
@@ -250,10 +312,10 @@ public class Javac {
* <code>compileExpr()</code>. The correct value of
* <code>isStatic</code> must be recorded before compilation.
*/
- public void recordParams(CtClass[] params, boolean isStatic)
+ public int recordParams(CtClass[] params, boolean isStatic)
throws CompileError
{
- gen.recordParams(params, isStatic, "$", "$args", "$$", stable);
+ return gen.recordParams(params, isStatic, "$", "$args", "$$", stable);
}
/**
@@ -273,12 +335,12 @@ public class Javac {
* @param isStatic true if the method in which the compiled bytecode
* is embedded is static.
*/
- public void recordParams(String target, CtClass[] params,
+ public int recordParams(String target, CtClass[] params,
boolean use0, int varNo, boolean isStatic)
throws CompileError
{
- gen.recordParams(params, isStatic, "$", "$args", "$$",
- use0, varNo, target, stable);
+ return gen.recordParams(params, isStatic, "$", "$args", "$$",
+ use0, varNo, target, stable);
}
/**
diff --git a/src/main/javassist/compiler/JvstCodeGen.java b/src/main/javassist/compiler/JvstCodeGen.java
index 07e7521b..6c78f477 100644
--- a/src/main/javassist/compiler/JvstCodeGen.java
+++ b/src/main/javassist/compiler/JvstCodeGen.java
@@ -462,13 +462,13 @@ public class JvstCodeGen extends MemberCodeGen {
* $0 is equivalent to THIS if the method is not static. Otherwise,
* if the method is static, then $0 is not available.
*/
- public void recordParams(CtClass[] params, boolean isStatic,
+ public int recordParams(CtClass[] params, boolean isStatic,
String prefix, String paramVarName,
String paramsName, SymbolTable tbl)
throws CompileError
{
- recordParams(params, isStatic, prefix, paramVarName,
- paramsName, !isStatic, 0, getThisName(), tbl);
+ return recordParams(params, isStatic, prefix, paramVarName,
+ paramsName, !isStatic, 0, getThisName(), tbl);
}
/**
@@ -484,11 +484,11 @@ public class JvstCodeGen extends MemberCodeGen {
* @param isStatic true if the method in which the compiled bytecode
* is embedded is static.
*/
- public void recordParams(CtClass[] params, boolean isStatic,
- String prefix, String paramVarName,
- String paramsName, boolean use0,
- int paramBase, String target,
- SymbolTable tbl)
+ public int recordParams(CtClass[] params, boolean isStatic,
+ String prefix, String paramVarName,
+ String paramsName, boolean use0,
+ int paramBase, String target,
+ SymbolTable tbl)
throws CompileError
{
int varNo;
@@ -516,6 +516,8 @@ public class JvstCodeGen extends MemberCodeGen {
if (getMaxLocals() < varNo)
setMaxLocals(varNo);
+
+ return varNo;
}
/**
@@ -574,9 +576,9 @@ public class JvstCodeGen extends MemberCodeGen {
String cname = null;
if (type == CLASS) {
if (dim == 0)
- cname = typeDesc;
+ cname = typeDesc.substring(1, typeDesc.length() - 1);
else
- cname = typeDesc.substring(dim);
+ cname = typeDesc.substring(dim + 1, typeDesc.length() - 1);
}
Declarator decl
diff --git a/src/main/javassist/expr/Cast.java b/src/main/javassist/expr/Cast.java
index 33324ce4..80ad4012 100644
--- a/src/main/javassist/expr/Cast.java
+++ b/src/main/javassist/expr/Cast.java
@@ -112,6 +112,7 @@ public class Cast extends Expr {
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
jc.compileStmnt(statement);
bytecode.addLoad(retVar, retType);
diff --git a/src/main/javassist/expr/FieldAccess.java b/src/main/javassist/expr/FieldAccess.java
index cc1f06f5..8598f456 100644
--- a/src/main/javassist/expr/FieldAccess.java
+++ b/src/main/javassist/expr/FieldAccess.java
@@ -188,6 +188,7 @@ public class FieldAccess extends Expr {
Bytecode bytecode = jc.getBytecode();
storeStack(params, isStatic(), paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
jc.compileStmnt(statement);
if (read)
bytecode.addLoad(retVar, retType);
diff --git a/src/main/javassist/expr/Instanceof.java b/src/main/javassist/expr/Instanceof.java
index 1421faee..a0982583 100644
--- a/src/main/javassist/expr/Instanceof.java
+++ b/src/main/javassist/expr/Instanceof.java
@@ -117,6 +117,7 @@ public class Instanceof extends Expr {
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
jc.compileStmnt(statement);
bytecode.addLoad(retVar, retType);
diff --git a/src/main/javassist/expr/MethodCall.java b/src/main/javassist/expr/MethodCall.java
index 60ec45da..28ed8d2d 100644
--- a/src/main/javassist/expr/MethodCall.java
+++ b/src/main/javassist/expr/MethodCall.java
@@ -210,6 +210,7 @@ public class MethodCall extends Expr {
Bytecode bytecode = jc.getBytecode();
storeStack(params, c == INVOKESTATIC, paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
jc.compileStmnt(statement);
if (retType != CtClass.voidType)
bytecode.addLoad(retVar, retType);
diff --git a/src/main/javassist/expr/NewExpr.java b/src/main/javassist/expr/NewExpr.java
index 9d4f20e1..1fa7d4e9 100644
--- a/src/main/javassist/expr/NewExpr.java
+++ b/src/main/javassist/expr/NewExpr.java
@@ -177,6 +177,7 @@ public class NewExpr extends Expr {
Bytecode bytecode = jc.getBytecode();
storeStack(params, true, paramVar, bytecode);
+ jc.recordLocalVariables(ca, pos);
jc.compileStmnt(statement);
bytecode.addAload(retVar);
diff --git a/tutorial/tutorial.html b/tutorial/tutorial.html
index 77c3dc97..c68eb814 100644
--- a/tutorial/tutorial.html
+++ b/tutorial/tutorial.html
@@ -690,6 +690,6 @@ binary code license.</i>
<hr>
Java(TM) is a trademark of Sun Microsystems, Inc.<br>
-Copyright (C) 2000-2003 by Shigeru Chiba, All rights reserved.
+Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.
</body>
</html>
diff --git a/tutorial/tutorial2.html b/tutorial/tutorial2.html
index 0e7530bf..b78c1ae1 100644
--- a/tutorial/tutorial2.html
+++ b/tutorial/tutorial2.html
@@ -149,12 +149,20 @@ 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.
+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">
@@ -166,8 +174,8 @@ below. Declaring a local variable in the block is allowed.
-->
<p>The <code>String</code> object passed to the methods
-<code>insertBefore()</code>, <code>insertAfter()</code>, and
-<code>addCatch()</code> are compiled by
+<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>
@@ -239,8 +247,7 @@ the class currently edited.</td>
<h4>$0, $1, $2, ...</h4>
-<p>The parameters passed to the methods <code>insertBefore()</code>,
-<code>insertAfter()</code>, and <code>addCatch()</code>
+<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.
@@ -685,6 +692,12 @@ object creation, or others. The second statement could be:
<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.
@@ -1318,6 +1331,6 @@ write:
<hr>
Java(TM) is a trademark of Sun Microsystems, Inc.<br>
-Copyright (C) 2000-2003 by Shigeru Chiba, All rights reserved.
+Copyright (C) 2000-2004 by Shigeru Chiba, All rights reserved.
</body>
</html>