/*
 * Javassist, a Java-bytecode translator toolkit.
 * Copyright (C) 1999- 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,
 * or the Apache License Version 2.0.
 *
 * 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;

import javassist.bytecode.BadBytecode;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
import javassist.bytecode.MethodInfo;
import javassist.convert.TransformAccessArrayField;
import javassist.convert.TransformAfter;
import javassist.convert.TransformBefore;
import javassist.convert.TransformCall;
import javassist.convert.TransformCallToStatic;
import javassist.convert.TransformFieldAccess;
import javassist.convert.TransformNew;
import javassist.convert.TransformNewClass;
import javassist.convert.TransformReadField;
import javassist.convert.TransformWriteField;
import javassist.convert.Transformer;

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:
/** * Simple translator of method bodies * (also see the <code>javassist.expr</code> package). * * <p>Instances of this class specifies how to instrument of the * bytecodes representing a method body. They are passed to * <code>CtClass.instrument()</code> or * <code>CtMethod.instrument()</code> as a parameter. * * <p>Example: * <pre> * 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); * </pre> * * <p>This program substitutes "<code>Singleton.makePoint()</code>" * for all occurrences of "<code>new Point()</code>" * appearing in methods declared in a <code>Client</code> class. * * @see javassist.CtClass#instrument(CodeConverter) * @see javassist.CtMethod#instrument(CodeConverter) * @see javassist.expr.ExprEditor */
public class CodeConverter { protected Transformer transformers = null;
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:
new Point(x, y)
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.

Params:
  • newClass – the instantiated class.
  • calledClass – the class in which the static method is declared.
  • calledMethod – the name of the static method.
/** * Modify a method body so that instantiation of the specified class * is replaced with a call to the specified static method. For example, * <code>replaceNew(ctPoint, ctSingleton, "createPoint")</code> * (where <code>ctPoint</code> and <code>ctSingleton</code> are * compile-time classes for class <code>Point</code> and class * <code>Singleton</code>, respectively) * replaces all occurrences of: * * <pre>new Point(x, y)</pre> * * in the method body with: * * <pre>Singleton.createPoint(x, y)</pre> * * <p>This enables to intercept instantiation of <code>Point</code> * and change the samentics. For example, the following * <code>createPoint()</code> implements the singleton pattern: * * <pre>public static Point createPoint(int x, int y) { * if (aPoint == null) * aPoint = new Point(x, y); * return aPoint; * } * </pre> * * <p>The static method call substituted for the original <code>new</code> * 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. * * <p>The return type of the substituted static method must be * the exactly same as the type of the instantiated class specified by * <code>newClass</code>. * * @param newClass the instantiated class. * @param calledClass the class in which the static method is * declared. * @param calledMethod the name of the static method. */
public void replaceNew(CtClass newClass, CtClass calledClass, String calledMethod) { transformers = new TransformNew(transformers, newClass.getName(), calledClass.getName(), calledMethod); }
Modify a method body so that instantiation of the class specified by oldClass is replaced with instantiation of another class newClass. For example, replaceNew(ctPoint, ctPoint2) (where ctPoint and ctPoint2 are compile-time classes for class Point and class Point2, respectively) replaces all occurrences of:
new Point(x, y)
in the method body with:
new Point2(x, y)

Note that Point2 must be type-compatible with Point. It must have the same set of methods, fields, and constructors as the replaced class.

/** * Modify a method body so that instantiation of the class * specified by <code>oldClass</code> * is replaced with instantiation of another class <code>newClass</code>. * For example, * <code>replaceNew(ctPoint, ctPoint2)</code> * (where <code>ctPoint</code> and <code>ctPoint2</code> are * compile-time classes for class <code>Point</code> and class * <code>Point2</code>, respectively) * replaces all occurrences of: * * <pre>new Point(x, y)</pre> * * in the method body with: * * <pre>new Point2(x, y)</pre> * * <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>. * It must have the same set of methods, fields, and constructors as the * replaced class. */
public void replaceNew(CtClass oldClass, CtClass newClass) { transformers = new TransformNewClass(transformers, oldClass.getName(), newClass.getName()); }
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.

Params:
  • field – the originally accessed field.
  • newClass – the class declaring the substituted field.
  • newFieldname – the name of the substituted field.
/** * Modify a method body so that field read/write expressions access * a different field from the original one. * * <p>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. * * <p>Also, <code>clazz</code> and <code>newClass</code> must specify * the class directly declaring the field. They must not specify * a subclass of that class. * * @param field the originally accessed field. * @param newClass the class declaring the substituted field. * @param newFieldname the name of the substituted field. */
public void redirectFieldAccess(CtField field, CtClass newClass, String newFieldname) { transformers = new TransformFieldAccess(transformers, field, newClass.getName(), newFieldname); }
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.

Params:
  • field – the field.
  • calledClass – the class in which the static method is declared.
  • calledMethod – the name of the static method.
/** * Modify a method body so that an expression reading the specified * field is replaced with a call to the specified <i>static</i> 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. * * <p>For example, the program below * * <pre>Point p = new Point(); * int newX = p.x + 3;</pre> * * <p>can be translated into: * * <pre>Point p = new Point(); * int newX = Accessor.readX(p) + 3;</pre> * * <p>where * * <pre>public class Accessor { * public static int readX(Object target) { ... } * }</pre> * * <p>The type of the parameter of <code>readX()</code> must * be <code>java.lang.Object</code> independently of the actual * type of <code>target</code>. The return type must be the same * as the field type. * * @param field the field. * @param calledClass the class in which the static method is * declared. * @param calledMethod the name of the static method. */
public void replaceFieldRead(CtField field, CtClass calledClass, String calledMethod) { transformers = new TransformReadField(transformers, field, calledClass.getName(), 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. 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.

Params:
  • field – the field.
  • calledClass – the class in which the static method is declared.
  • calledMethod – the name of the static method.
/** * 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 <code>void</code>. * * <p>For example, the program below * * <pre>Point p = new Point(); * p.x = 3;</pre> * * <p>can be translated into: * * <pre>Point p = new Point(); * Accessor.writeX(3);</pre> * * <p>where * * <pre>public class Accessor { * public static void writeX(Object target, int value) { ... } * }</pre> * * <p>The type of the first parameter of <code>writeX()</code> must * be <code>java.lang.Object</code> independently of the actual * type of <code>target</code>. The type of the second parameter * is the same as the field type. * * @param field the field. * @param calledClass the class in which the static method is * declared. * @param calledMethod the name of the static method. */
public void replaceFieldWrite(CtField field, CtClass calledClass, String calledMethod) { transformers = new TransformWriteField(transformers, field, calledClass.getName(), calledMethod); }
Modify a method body, so that ALL accesses to an array are replaced with calls to static methods within another class. In the case of reading an element from the array, this is replaced with a call to a static method with the array and the index as arguments, the return value is the value read from the array. If writing to an array, this is replaced with a call to a static method with the array, index and new value as parameters, the return value of the static method is void.

The calledClass parameter is the class containing the static methods to be used for array replacement. The names parameter points to an implementation of ArrayAccessReplacementMethodNames which specifies the names of the method to be used for access for each type of array. For example reading from an int[] will require a different method than if writing to an int[], and writing to a long[] will require a different method than if writing to a byte[]. If the implementation of ArrayAccessReplacementMethodNames does not contain the name for access for a type of array, that access is not replaced.

A default implementation of ArrayAccessReplacementMethodNames called DefaultArrayAccessReplacementMethodNames has been provided and is what is used in the following example. This also assumes that 'foo.ArrayAdvisor' is the name of the CtClass passed in.

If we have the following class:

class POJO{
   int[] ints = new int[]{1, 2, 3, 4, 5};
   long[] longs = new int[]{10, 20, 30};
   Object objects = new Object[]{true, false};
   Integer[] integers = new Integer[]{new Integer(10)};
}
and this is accessed as:
POJO p = new POJO();
//Write to int array
p.ints[2] = 7;
//Read from int array
int i = p.ints[2];
//Write to long array
p.longs[2] = 1000L;
//Read from long array
long l = p.longs[2];
//Write to Object array
p.objects[2] = "Hello";
//Read from Object array
Object o = p.objects[2];
//Write to Integer array
Integer integer = new Integer(5);
p.integers[0] = integer;
//Read from Object array
integer = p.integers[0];
Following instrumentation we will have
POJO p = new POJO();
//Write to int array
ArrayAdvisor.arrayWriteInt(p.ints, 2, 7);
//Read from int array
int i = ArrayAdvisor.arrayReadInt(p.ints, 2);
//Write to long array
ArrayAdvisor.arrayWriteLong(p.longs, 2, 1000L);
//Read from long array
long l = ArrayAdvisor.arrayReadLong(p.longs, 2);
//Write to Object array
ArrayAdvisor.arrayWriteObject(p.objects, 2, "Hello");
//Read from Object array
Object o = ArrayAdvisor.arrayReadObject(p.objects, 2);
//Write to Integer array
Integer integer = new Integer(5);
ArrayAdvisor.arrayWriteObject(p.integers, 0, integer);
//Read from Object array
integer = ArrayAdvisor.arrayWriteObject(p.integers, 0);
Params:
  • calledClass – the class containing the static methods.
  • names – contains the names of the methods to replace the different kinds of array access with.
See Also:
  • DefaultArrayAccessReplacementMethodNames
/** * Modify a method body, so that ALL accesses to an array are replaced with * calls to static methods within another class. In the case of reading an * element from the array, this is replaced with a call to a static method with * the array and the index as arguments, the return value is the value read from * the array. If writing to an array, this is replaced with a call to a static * method with the array, index and new value as parameters, the return value of * the static method is <code>void</code>. * * <p>The <code>calledClass</code> parameter is the class containing the static methods to be used * for array replacement. The <code>names</code> parameter points to an implementation of * <code>ArrayAccessReplacementMethodNames</code> which specifies the names of the method to be * used for access for each type of array. For example reading from an <code>int[]</code> will * require a different method than if writing to an <code>int[]</code>, and writing to a <code>long[]</code> * will require a different method than if writing to a <code>byte[]</code>. If the implementation * of <code>ArrayAccessReplacementMethodNames</code> does not contain the name for access for a * type of array, that access is not replaced. * * <p>A default implementation of <code>ArrayAccessReplacementMethodNames</code> called * <code>DefaultArrayAccessReplacementMethodNames</code> has been provided and is what is used in the * following example. This also assumes that <code>'foo.ArrayAdvisor'</code> is the name of the * <code>CtClass</code> passed in. * * <p>If we have the following class: * <pre>class POJO{ * int[] ints = new int[]{1, 2, 3, 4, 5}; * long[] longs = new int[]{10, 20, 30}; * Object objects = new Object[]{true, false}; * Integer[] integers = new Integer[]{new Integer(10)}; * } * </pre> * and this is accessed as: * <pre>POJO p = new POJO(); * * //Write to int array * p.ints[2] = 7; * * //Read from int array * int i = p.ints[2]; * * //Write to long array * p.longs[2] = 1000L; * * //Read from long array * long l = p.longs[2]; * * //Write to Object array * p.objects[2] = "Hello"; * * //Read from Object array * Object o = p.objects[2]; * * //Write to Integer array * Integer integer = new Integer(5); * p.integers[0] = integer; * * //Read from Object array * integer = p.integers[0]; * </pre> * * Following instrumentation we will have * <pre>POJO p = new POJO(); * * //Write to int array * ArrayAdvisor.arrayWriteInt(p.ints, 2, 7); * * //Read from int array * int i = ArrayAdvisor.arrayReadInt(p.ints, 2); * * //Write to long array * ArrayAdvisor.arrayWriteLong(p.longs, 2, 1000L); * * //Read from long array * long l = ArrayAdvisor.arrayReadLong(p.longs, 2); * * //Write to Object array * ArrayAdvisor.arrayWriteObject(p.objects, 2, "Hello"); * * //Read from Object array * Object o = ArrayAdvisor.arrayReadObject(p.objects, 2); * * //Write to Integer array * Integer integer = new Integer(5); * ArrayAdvisor.arrayWriteObject(p.integers, 0, integer); * * //Read from Object array * integer = ArrayAdvisor.arrayWriteObject(p.integers, 0); * </pre> * * @see DefaultArrayAccessReplacementMethodNames * * @param calledClass the class containing the static methods. * @param names contains the names of the methods to replace * the different kinds of array access with. */
public void replaceArrayAccess(CtClass calledClass, ArrayAccessReplacementMethodNames names) throws NotFoundException { transformers = new TransformAccessArrayField(transformers, calledClass.getName(), names); }
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.

Params:
  • origMethod – original method
  • substMethod – substituted method
/** * Modify method invocations in a method body so that a different * method will be invoked. * * <p>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. * * @param origMethod original method * @param substMethod substituted method */
public void redirectMethodCall(CtMethod origMethod, CtMethod substMethod) throws CannotCompileException { String d1 = origMethod.getMethodInfo2().getDescriptor(); String d2 = substMethod.getMethodInfo2().getDescriptor(); if (!d1.equals(d2)) throw new CannotCompileException("signature mismatch: " + substMethod.getLongName()); int mod1 = origMethod.getModifiers(); int mod2 = substMethod.getModifiers(); if (Modifier.isStatic(mod1) != Modifier.isStatic(mod2) || (Modifier.isPrivate(mod1) && !Modifier.isPrivate(mod2)) || origMethod.getDeclaringClass().isInterface() != substMethod.getDeclaringClass().isInterface()) throw new CannotCompileException("invoke-type mismatch " + substMethod.getLongName()); transformers = new TransformCall(transformers, origMethod, substMethod); }
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.

Params:
  • oldMethodName – the old name of the method.
  • newMethod – the method with the new name.
See Also:
/** * 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. * * <p>The method must be declared in the same class before and * after it is renamed. * * <p>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. * * @param oldMethodName the old name of the method. * @param newMethod the method with the new name. * @see javassist.CtMethod#setName(String) */
public void redirectMethodCall(String oldMethodName, CtMethod newMethod) throws CannotCompileException { transformers = new TransformCall(transformers, oldMethodName, newMethod); }
Redirect non-static method invocations in a method body to a static method. The return type must be same with the originally invoked method. As parameters, the static 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 static method must be something like this:

class Verbose {
    static Point 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:

Point p2 = Verbose.print(p, x + y, 0);
Params:
  • origMethod – original method
  • staticMethod – static method
/** * Redirect non-static method invocations in a method body to a static * method. The return type must be same with the originally invoked method. * As parameters, the static method receives * the target object and all the parameters to the originally invoked * method. For example, if the originally invoked method is * <code>move()</code>: * * <pre>class Point { * Point move(int x, int y) { ... } * }</pre> * * <p>Then the static method must be something like this: * * <pre>class Verbose { * static Point print(Point target, int x, int y) { ... } * }</pre> * * <p>The <code>CodeConverter</code> would translate bytecode * equivalent to: * * <pre>Point p2 = p.move(x + y, 0);</pre> * * <p>into the bytecode equivalent to: * * <pre>Point p2 = Verbose.print(p, x + y, 0);</pre> * * @param origMethod original method * @param staticMethod static method */
public void redirectMethodCallToStatic(CtMethod origMethod, CtMethod staticMethod) { transformers = new TransformCallToStatic(transformers, origMethod, staticMethod); }
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);
Params:
  • origMethod – the method originally invoked.
  • beforeMethod – the method invoked before origMethod.
/** * Insert a call to another method before an existing method call. * That "before" method must be static. The return type must be * <code>void</code>. 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 * <code>move()</code>: * * <pre>class Point { * Point move(int x, int y) { ... } * }</pre> * * <p>Then the before method must be something like this: * * <pre>class Verbose { * static void print(Point target, int x, int y) { ... } * }</pre> * * <p>The <code>CodeConverter</code> would translate bytecode * equivalent to: * * <pre>Point p2 = p.move(x + y, 0);</pre> * * <p>into the bytecode equivalent to: * * <pre>int tmp1 = x + y; * int tmp2 = 0; * Verbose.print(p, tmp1, tmp2); * Point p2 = p.move(tmp1, tmp2);</pre> * * @param origMethod the method originally invoked. * @param beforeMethod the method invoked before * <code>origMethod</code>. */
public void insertBeforeMethod(CtMethod origMethod, CtMethod beforeMethod) throws CannotCompileException { try { transformers = new TransformBefore(transformers, origMethod, beforeMethod); } catch (NotFoundException e) { throw new CannotCompileException(e); } }
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);
Params:
  • origMethod – the method originally invoked.
  • afterMethod – the method invoked after origMethod.
/** * Inserts a call to another method after an existing method call. * That "after" method must be static. The return type must be * <code>void</code>. 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 * <code>move()</code>: * * <pre>class Point { * Point move(int x, int y) { ... } * }</pre> * * <p>Then the after method must be something like this: * * <pre>class Verbose { * static void print(Point target, int x, int y) { ... } * }</pre> * * <p>The <code>CodeConverter</code> would translate bytecode * equivalent to: * * <pre>Point p2 = p.move(x + y, 0);</pre> * * <p>into the bytecode equivalent to: * * <pre> * int tmp1 = x + y; * int tmp2 = 0; * Point p2 = p.move(tmp1, tmp2); * Verbose.print(p, tmp1, tmp2);</pre> * * @param origMethod the method originally invoked. * @param afterMethod the method invoked after * <code>origMethod</code>. */
public void insertAfterMethod(CtMethod origMethod, CtMethod afterMethod) throws CannotCompileException { try { transformers = new TransformAfter(transformers, origMethod, afterMethod); } catch (NotFoundException e) { throw new CannotCompileException(e); } }
Performs code conversion.
/** * Performs code conversion. */
protected void doit(CtClass clazz, MethodInfo minfo, ConstPool cp) throws CannotCompileException { Transformer t; CodeAttribute codeAttr = minfo.getCodeAttribute(); if (codeAttr == null || transformers == null) return; for (t = transformers; t != null; t = t.getNext()) t.initialize(cp, clazz, minfo); CodeIterator iterator = codeAttr.iterator(); while (iterator.hasNext()) { try { int pos = iterator.next(); for (t = transformers; t != null; t = t.getNext()) pos = t.transform(clazz, pos, iterator, cp); } catch (BadBytecode e) { throw new CannotCompileException(e); } } int locals = 0; int stack = 0; for (t = transformers; t != null; t = t.getNext()) { int s = t.extraLocals(); if (s > locals) locals = s; s = t.extraStack(); if (s > stack) stack = s; } for (t = transformers; t != null; t = t.getNext()) t.clean(); if (locals > 0) codeAttr.setMaxLocals(codeAttr.getMaxLocals() + locals); if (stack > 0) codeAttr.setMaxStack(codeAttr.getMaxStack() + stack); try { minfo.rebuildStackMapIf6(clazz.getClassPool(), clazz.getClassFile2()); } catch (BadBytecode b) { throw new CannotCompileException(b.getMessage(), b); } }
Interface containing the method names to be used as array access replacements.
Author:Kabir Khan
Version:$Revision: 1.16 $
/** * Interface containing the method names to be used * as array access replacements. * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> * @version $Revision: 1.16 $ */
public interface ArrayAccessReplacementMethodNames {
Returns the name of a static method with the signature (Ljava/lang/Object;I)B to replace reading from a byte[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)B</code> to replace reading from a byte[]. */
String byteOrBooleanRead();
Returns the name of a static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;IB)V</code> to replace writing to a byte[]. */
String byteOrBooleanWrite();
Returns:the name of a static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[].
/** * @return the name of a static method with the signature * <code>(Ljava/lang/Object;I)C</code> to replace reading from a char[]. */
String charRead();
Returns the name of a static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;IC)V</code> to replace writing to a byte[]. */
String charWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)D</code> to replace reading from a double[]. */
String doubleRead();
Returns the name of a static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;ID)V</code> to replace writing to a double[]. */
String doubleWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)F</code> to replace reading from a float[]. */
String floatRead();
Returns the name of a static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;IF)V</code> to replace writing to a float[]. */
String floatWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)I</code> to replace reading from a int[]. */
String intRead();
Returns the name of a static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;II)V</code> to replace writing to a int[]. */
String intWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)J</code> to replace reading from a long[]. */
String longRead();
Returns the name of a static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;IJ)V</code> to replace writing to a long[]. */
String longWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object).
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)Ljava/lang/Object;</code> * to replace reading from a Object[] (or any subclass of object). */
String objectRead();
Returns the name of a static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object).
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;ILjava/lang/Object;)V</code> * to replace writing to a Object[] (or any subclass of object). */
String objectWrite();
Returns the name of a static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;I)S</code> to replace reading from a short[]. */
String shortRead();
Returns the name of a static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[].
/** * Returns the name of a static method with the signature * <code>(Ljava/lang/Object;IS)V</code> to replace writing to a short[]. */
String shortWrite(); }
Default implementation of the ArrayAccessReplacementMethodNames interface giving default values for method names to be used for replacing accesses to array elements.
Author:Kabir Khan
Version:$Revision: 1.16 $
/** * Default implementation of the <code>ArrayAccessReplacementMethodNames</code> * interface giving default values for method names to be used for replacing * accesses to array elements. * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> * @version $Revision: 1.16 $ */
public static class DefaultArrayAccessReplacementMethodNames implements ArrayAccessReplacementMethodNames {
Returns "arrayReadByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;I)B to replace reading from a byte[].
/** * Returns "arrayReadByteOrBoolean" as the name of the static method with the signature * (Ljava/lang/Object;I)B to replace reading from a byte[]. */
@Override public String byteOrBooleanRead() { return "arrayReadByteOrBoolean"; }
Returns "arrayWriteByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[].
/** * Returns "arrayWriteByteOrBoolean" as the name of the static method with the signature * (Ljava/lang/Object;IB)V to replace writing to a byte[]. */
@Override public String byteOrBooleanWrite() { return "arrayWriteByteOrBoolean"; }
Returns "arrayReadChar" as the name of the static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[].
/** * Returns "arrayReadChar" as the name of the static method with the signature * (Ljava/lang/Object;I)C to replace reading from a char[]. */
@Override public String charRead() { return "arrayReadChar"; }
Returns "arrayWriteChar" as the name of the static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[].
/** * Returns "arrayWriteChar" as the name of the static method with the signature * (Ljava/lang/Object;IC)V to replace writing to a byte[]. */
@Override public String charWrite() { return "arrayWriteChar"; }
Returns "arrayReadDouble" as the name of the static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[].
/** * Returns "arrayReadDouble" as the name of the static method with the signature * (Ljava/lang/Object;I)D to replace reading from a double[]. */
@Override public String doubleRead() { return "arrayReadDouble"; }
Returns "arrayWriteDouble" as the name of the static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[].
/** * Returns "arrayWriteDouble" as the name of the static method with the signature * (Ljava/lang/Object;ID)V to replace writing to a double[]. */
@Override public String doubleWrite() { return "arrayWriteDouble"; }
Returns "arrayReadFloat" as the name of the static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[].
/** * Returns "arrayReadFloat" as the name of the static method with the signature * (Ljava/lang/Object;I)F to replace reading from a float[]. */
@Override public String floatRead() { return "arrayReadFloat"; }
Returns "arrayWriteFloat" as the name of the static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[].
/** * Returns "arrayWriteFloat" as the name of the static method with the signature * (Ljava/lang/Object;IF)V to replace writing to a float[]. */
@Override public String floatWrite() { return "arrayWriteFloat"; }
Returns "arrayReadInt" as the name of the static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[].
/** * Returns "arrayReadInt" as the name of the static method with the signature * (Ljava/lang/Object;I)I to replace reading from a int[]. */
@Override public String intRead() { return "arrayReadInt"; }
Returns "arrayWriteInt" as the name of the static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[].
/** * Returns "arrayWriteInt" as the name of the static method with the signature * (Ljava/lang/Object;II)V to replace writing to a int[]. */
@Override public String intWrite() { return "arrayWriteInt"; }
Returns "arrayReadLong" as the name of the static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[].
/** * Returns "arrayReadLong" as the name of the static method with the signature * (Ljava/lang/Object;I)J to replace reading from a long[]. */
@Override public String longRead() { return "arrayReadLong"; }
Returns "arrayWriteLong" as the name of the static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[].
/** * Returns "arrayWriteLong" as the name of the static method with the signature * (Ljava/lang/Object;IJ)V to replace writing to a long[]. */
@Override public String longWrite() { return "arrayWriteLong"; }
Returns "arrayReadObject" as the name of the static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object).
/** * Returns "arrayReadObject" as the name of the static method with the signature * (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object). */
@Override public String objectRead() { return "arrayReadObject"; }
Returns "arrayWriteObject" as the name of the static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object).
/** * Returns "arrayWriteObject" as the name of the static method with the signature * (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object). */
@Override public String objectWrite() { return "arrayWriteObject"; }
Returns "arrayReadShort" as the name of the static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[].
/** * Returns "arrayReadShort" as the name of the static method with the signature * (Ljava/lang/Object;I)S to replace reading from a short[]. */
@Override public String shortRead() { return "arrayReadShort"; }
Returns "arrayWriteShort" as the name of the static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[].
/** * Returns "arrayWriteShort" as the name of the static method with the signature * (Ljava/lang/Object;IS)V to replace writing to a short[]. */
@Override public String shortWrite() { return "arrayWriteShort"; } } }