| java.lang.Object javassist.CodeConverter
CodeConverter | public class CodeConverter (Code) | | Simple translator of method bodies
(also see the javassist.expr package).
Instances of this class specifies how to instrument of the
bytecodes representing a method body. They are passed to
CtClass.instrument() or
CtMethod.instrument() as a parameter.
Example:
ClassPool cp = ClassPool.getDefault();
CtClass point = cp.get("Point");
CtClass singleton = cp.get("Singleton");
CtClass client = cp.get("Client");
CodeConverter conv = new CodeConverter();
conv.replaceNew(point, singleton, "makePoint");
client.instrument(conv);
This program substitutes "Singleton.makePoint() "
for all occurrences of "new Point() "
appearing in methods declared in a Client class.
See Also: javassist.CtClass.instrument(CodeConverter) See Also: javassist.CtMethod.instrument(CodeConverter) See Also: javassist.expr.ExprEditor |
Method Summary | |
void | doit(CtClass clazz, MethodInfo minfo, ConstPool cp) Performs code conversion. | public void | insertAfterMethod(CtMethod origMethod, CtMethod afterMethod) Inserts a call to another method after an existing method call.
That "after" method must be static. | public void | insertBeforeMethod(CtMethod origMethod, CtMethod beforeMethod) Insert a call to another method before an existing method call.
That "before" method must be static. | public void | redirectFieldAccess(CtField field, CtClass newClass, String newFieldname) Modify a method body so that field read/write expressions access
a different field from the original one.
Note that this method changes only the filed name and the class
declaring the field; the type of the target object does not change.
Therefore, the substituted field must be declared in the same class
or a superclass of the original class.
Also, clazz and newClass must specify
the class directly declaring the field. | public void | redirectMethodCall(CtMethod origMethod, CtMethod substMethod) Modify method invocations in a method body so that a different
method will be invoked.
Note that the target object, the parameters, or
the type of invocation
(static method call, interface call, or private method call)
are not modified. | public void | redirectMethodCall(String oldMethodName, CtMethod newMethod) Correct invocations to a method that has been renamed.
If a method is renamed, calls to that method must be also
modified so that the method with the new name will be called.
The method must be declared in the same class before and
after it is renamed.
Note that the target object, the parameters, or
the type of invocation
(static method call, interface call, or private method call)
are not modified. | public void | replaceFieldRead(CtField field, CtClass calledClass, String calledMethod) Modify a method body so that an expression reading the specified
field is replaced with a call to the specified static method.
This static method receives the target object of the original
read expression as a parameter. | public void | replaceFieldWrite(CtField field, CtClass calledClass, String calledMethod) Modify a method body so that an expression writing the specified
field is replaced with a call to the specified static method.
This static method receives two parameters: the target object of
the original
write expression and the assigned value. | public void | replaceNew(CtClass newClass, CtClass calledClass, String calledMethod) Modify a method body so that instantiation of the specified class
is replaced with a call to the specified static method. |
insertAfterMethod | public void insertAfterMethod(CtMethod origMethod, CtMethod afterMethod) throws CannotCompileException(Code) | | Inserts a call to another method after an existing method call.
That "after" method must be static. The return type must be
void . As parameters, the after method receives
the target object and all the parameters to the originally invoked
method. For example, if the originally invoked method is
move() :
class Point {
Point move(int x, int y) { ... }
}
Then the after method must be something like this:
class Verbose {
static void print(Point target, int x, int y) { ... }
}
The CodeConverter would translate bytecode
equivalent to:
Point p2 = p.move(x + y, 0);
into the bytecode equivalent to:
int tmp1 = x + y;
int tmp2 = 0;
Point p2 = p.move(tmp1, tmp2);
Verbose.print(p, tmp1, tmp2);
Parameters: origMethod - the method originally invoked. Parameters: afterMethod - the method invoked afterorigMethod . |
insertBeforeMethod | public void insertBeforeMethod(CtMethod origMethod, CtMethod beforeMethod) throws CannotCompileException(Code) | | Insert a call to another method before an existing method call.
That "before" method must be static. The return type must be
void . As parameters, the before method receives
the target object and all the parameters to the originally invoked
method. For example, if the originally invoked method is
move() :
class Point {
Point move(int x, int y) { ... }
}
Then the before method must be something like this:
class Verbose {
static void print(Point target, int x, int y) { ... }
}
The CodeConverter would translate bytecode
equivalent to:
Point p2 = p.move(x + y, 0);
into the bytecode equivalent to:
int tmp1 = x + y;
int tmp2 = 0;
Verbose.print(p, tmp1, tmp2);
Point p2 = p.move(tmp1, tmp2);
Parameters: origMethod - the method originally invoked. Parameters: beforeMethod - the method invoked beforeorigMethod . |
redirectFieldAccess | public void redirectFieldAccess(CtField field, CtClass newClass, String newFieldname)(Code) | | Modify a method body so that field read/write expressions access
a different field from the original one.
Note that this method changes only the filed name and the class
declaring the field; the type of the target object does not change.
Therefore, the substituted field must be declared in the same class
or a superclass of the original class.
Also, clazz and newClass must specify
the class directly declaring the field. They must not specify
a subclass of that class.
Parameters: field - the originally accessed field. Parameters: newClass - the class declaring the substituted field. Parameters: newFieldname - the name of the substituted field. |
redirectMethodCall | public void redirectMethodCall(CtMethod origMethod, CtMethod substMethod) throws CannotCompileException(Code) | | Modify method invocations in a method body so that a different
method will be invoked.
Note that the target object, the parameters, or
the type of invocation
(static method call, interface call, or private method call)
are not modified. Only the method name is changed. The substituted
method must have the same signature that the original one has.
If the original method is a static method, the substituted method
must be static.
Parameters: origMethod - original method Parameters: substMethod - substituted method |
redirectMethodCall | public void redirectMethodCall(String oldMethodName, CtMethod newMethod) throws CannotCompileException(Code) | | Correct invocations to a method that has been renamed.
If a method is renamed, calls to that method must be also
modified so that the method with the new name will be called.
The method must be declared in the same class before and
after it is renamed.
Note that the target object, the parameters, or
the type of invocation
(static method call, interface call, or private method call)
are not modified. Only the method name is changed.
Parameters: oldMethodName - the old name of the method. Parameters: newMethod - the method with the new name. See Also: javassist.CtMethod.setName(String) |
replaceFieldRead | public void replaceFieldRead(CtField field, CtClass calledClass, String calledMethod)(Code) | | Modify a method body so that an expression reading the specified
field is replaced with a call to the specified static method.
This static method receives the target object of the original
read expression as a parameter. It must return a value of
the same type as the field.
For example, the program below
Point p = new Point();
int newX = p.x + 3;
can be translated into:
Point p = new Point();
int newX = Accessor.readX(p) + 3;
where
public class Accessor {
public static int readX(Object target) { ... }
}
The type of the parameter of readX() must
be java.lang.Object independently of the actual
type of target . The return type must be the same
as the field type.
Parameters: field - the field. Parameters: calledClass - the class in which the static method isdeclared. Parameters: calledMethod - the name of the static method. |
replaceFieldWrite | public void replaceFieldWrite(CtField field, CtClass calledClass, String calledMethod)(Code) | | Modify a method body so that an expression writing the specified
field is replaced with a call to the specified static method.
This static method receives two parameters: the target object of
the original
write expression and the assigned value. The return type of the
static method is void .
For example, the program below
Point p = new Point();
p.x = 3;
can be translated into:
Point p = new Point();
Accessor.writeX(3);
where
public class Accessor {
public static void writeX(Object target, int value) { ... }
}
The type of the first parameter of writeX() must
be java.lang.Object independently of the actual
type of target . The type of the second parameter
is the same as the field type.
Parameters: field - the field. Parameters: calledClass - the class in which the static method isdeclared. Parameters: calledMethod - the name of the static method. |
replaceNew | public void replaceNew(CtClass newClass, CtClass calledClass, String calledMethod)(Code) | | Modify a method body so that instantiation of the specified class
is replaced with a call to the specified static method. For example,
replaceNew(ctPoint, ctSingleton, "createPoint")
(where ctPoint and ctSingleton are
compile-time classes for class Point and class
Singleton , respectively)
replaces all occurrences of:
in the method body with:
Singleton.createPoint(x, y)
This enables to intercept instantiation of Point
and change the samentics. For example, the following
createPoint() implements the singleton pattern:
public static Point createPoint(int x, int y) {
if (aPoint == null)
aPoint = new Point(x, y);
return aPoint;
}
The static method call substituted for the original new
expression must be
able to receive the same set of parameters as the original
constructor. If there are multiple constructors with different
parameter types, then there must be multiple static methods
with the same name but different parameter types.
The return type of the substituted static method must be
the exactly same as the type of the instantiated class specified by
newClass .
Parameters: newClass - the instantiated class. Parameters: calledClass - the class in which the static method isdeclared. Parameters: calledMethod - the name of the static method. |
|
|