Bladeren bron

Document CodeConverter.replaceArrayAccess()


git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@340 30ef5769-5b8d-40dd-aea6-55b5d6557bb3
tags/rel_3_17_1_ga
kkhan 17 jaren geleden
bovenliggende
commit
956be9c3df
2 gewijzigde bestanden met toevoegingen van 333 en 179 verwijderingen
  1. 329
    9
      src/main/javassist/CodeConverter.java
  2. 4
    170
      src/main/javassist/convert/TransformAccessArrayField.java

+ 329
- 9
src/main/javassist/CodeConverter.java Bestand weergeven

@@ -17,7 +17,6 @@ package javassist;

import javassist.bytecode.*;
import javassist.convert.*;
import javassist.convert.TransformAccessArrayField.MethodNames;

/**
* Simple translator of method bodies
@@ -48,7 +47,7 @@ import javassist.convert.TransformAccessArrayField.MethodNames;
* @see javassist.expr.ExprEditor
*/
public class CodeConverter {
Transformer transformers = null;
protected Transformer transformers = null;

/**
* Modify a method body so that instantiation of the specified class
@@ -64,7 +63,7 @@ public class CodeConverter {
* in the method body with:
*
* <ul><code>Singleton.createPoint(x, y)</code></ul>
*
*
* <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:
@@ -169,7 +168,7 @@ public class CodeConverter {
* 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
*
* <ul><pre>Point p = new Point();
@@ -203,16 +202,110 @@ public class CodeConverter {
calledMethod);
}

public void replaceArrayAccess(CtClass calledClass, MethodNames names) throws NotFoundException
/**
* 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 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.
*
* <p>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.
*
* <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.
*
* <p>Note that the target object, the parameters, or
* <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
@@ -254,7 +347,7 @@ public class CodeConverter {
* <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
* <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.
@@ -368,7 +461,7 @@ public class CodeConverter {
/**
* Performs code conversion.
*/
void doit(CtClass clazz, MethodInfo minfo, ConstPool cp)
protected void doit(CtClass clazz, MethodInfo minfo, ConstPool cp)
throws CannotCompileException
{
Transformer t;
@@ -403,4 +496,231 @@ public class CodeConverter {

codeAttr.setMaxLocals(codeAttr.getMaxLocals() + locals);
}

/**
* 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.11 $
*/
public interface ArrayAccessReplacementMethodNames
{
/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)B" to replace reading from a byte[]
*/
String byteOrBooleanRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[]
*/
String byteOrBooleanWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[]
*/
String charRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[]
*/
String charWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[]
*/
String doubleRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[]
*/
String doubleWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[]
*/
String floatRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[]
*/
String floatWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[]
*/
String intRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[]
*/
String intWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[]
*/
String longRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[]
*/
String longWrite();

/**
* @return 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)
*/
String objectRead();

/**
* @return 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)
*/
String objectWrite();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[]
*/
String shortRead();

/**
* @return the name of a static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[]
*/
String shortWrite();
}

/**
* Default implementation of the MethodNames 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.11 $
*/
public static class DefaultArrayAccessReplacementMethodNames implements ArrayAccessReplacementMethodNames
{

/**
* @return "arrayReadByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;I)B" to replace reading from a byte[]
*/
public String byteOrBooleanRead()
{
return "arrayReadByteOrBoolean";
}

/**
* @return "arrayWriteByteOrBoolean" as the name of the static method with the signature (Ljava/lang/Object;IB)V to replace writing to a byte[]
*/
public String byteOrBooleanWrite()
{
return "arrayWriteByteOrBoolean";
}

/**
* @return "arrayReadChar" as the name of the static method with the signature (Ljava/lang/Object;I)C to replace reading from a char[]
*/
public String charRead()
{
return "arrayReadChar";
}

/**
* @return "arrayWriteChar" as the name of the static method with the signature (Ljava/lang/Object;IC)V to replace writing to a byte[]
*/
public String charWrite()
{
return "arrayWriteChar";
}

/**
* @return "arrayReadDouble" as the name of the static method with the signature (Ljava/lang/Object;I)D to replace reading from a double[]
*/
public String doubleRead()
{
return "arrayReadDouble";
}

/**
* @return "arrayWriteDouble" as the name of the static method with the signature (Ljava/lang/Object;ID)V to replace writing to a double[]
*/
public String doubleWrite()
{
return "arrayWriteDouble";
}

/**
* @return "arrayReadFloat" as the name of the static method with the signature (Ljava/lang/Object;I)F to replace reading from a float[]
*/
public String floatRead()
{
return "arrayReadFloat";
}

/**
* @return "arrayWriteFloat" as the name of the static method with the signature (Ljava/lang/Object;IF)V to replace writing to a float[]
*/
public String floatWrite()
{
return "arrayWriteFloat";
}

/**
* @return "arrayReadInt" as the name of the static method with the signature (Ljava/lang/Object;I)I to replace reading from a int[]
*/
public String intRead()
{
return "arrayReadInt";
}

/**
* @return "arrayWriteInt" as the name of the static method with the signature (Ljava/lang/Object;II)V to replace writing to a int[]
*/
public String intWrite()
{
return "arrayWriteInt";
}

/**
* @return "arrayReadLong" as the name of the static method with the signature (Ljava/lang/Object;I)J to replace reading from a long[]
*/
public String longRead()
{
return "arrayReadLong";
}

/**
* @return "arrayWriteLong" as the name of the static method with the signature (Ljava/lang/Object;IJ)V to replace writing to a long[]
*/
public String longWrite()
{
return "arrayWriteLong";
}

/**
* @return "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)
*/
public String objectRead()
{
return "arrayReadObject";
}

/**
* @return "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)
*/
public String objectWrite()
{
return "arrayWriteObject";
}

/**
* @return "arrayReadShort" as the name of the static method with the signature (Ljava/lang/Object;I)S to replace reading from a short[]
*/
public String shortRead()
{
return "arrayReadShort";
}

/**
* @return "arrayWriteShort" as the name of the static method with the signature (Ljava/lang/Object;IS)V to replace writing to a short[]
*/
public String shortWrite()
{
return "arrayWriteShort";
}
}
}

+ 4
- 170
src/main/javassist/convert/TransformAccessArrayField.java Bestand weergeven

@@ -17,6 +17,7 @@ package javassist.convert;

import javassist.CtClass;
import javassist.NotFoundException;
import javassist.CodeConverter.ArrayAccessReplacementMethodNames;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
@@ -24,16 +25,16 @@ import javassist.bytecode.ConstPool;
/**
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @version $Revision: 1.1 $
* @version $Revision: 1.2 $
*/
public class TransformAccessArrayField extends Transformer
{
// CtClass componentType;

String methodClassname;
MethodNames names;
ArrayAccessReplacementMethodNames names;

public TransformAccessArrayField(Transformer next, String methodClassname, MethodNames names) throws NotFoundException
public TransformAccessArrayField(Transformer next, String methodClassname, ArrayAccessReplacementMethodNames names) throws NotFoundException
{
super(next);
this.methodClassname = methodClassname;
@@ -179,171 +180,4 @@ public class TransformAccessArrayField extends Transformer
}
throw new BadBytecode(opcode);
}
public interface MethodNames
{
/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)Ljava/lang/Object;
*/
String objectRead();
/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)B"
*/
String byteOrBooleanRead();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)C
*/
String charRead();
/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)D
*/
String doubleRead();
/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)F
*/
String floatRead();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)I
*/
String intRead();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)J
*/
String longRead();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;I)S
*/
String shortRead();
/**
* Give the name of a static method with the signature (Ljava/lang/Object;ILjava/lang/Object;)V
*/
String objectWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;IB)V
*/
String byteOrBooleanWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;IC)V
*/
String charWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;ID)V
*/
String doubleWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;IF)V
*/
String floatWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;II)V
*/
String intWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;IJ)V
*/
String longWrite();

/**
* Give the name of a static method with the signature (Ljava/lang/Object;IS)V
*/
String shortWrite();
}
public static class DefaultMethodNames implements MethodNames
{
public String byteOrBooleanRead()
{
return "arrayReadByteOrBoolean";
}

public String byteOrBooleanWrite()
{
return "arrayWriteByteOrBoolean";
}

public String charRead()
{
return "arrayReadChar";
}

public String charWrite()
{
return "arrayWriteChar";
}

public String doubleRead()
{
return "arrayReadDouble";
}

public String doubleWrite()
{
return "arrayWriteDouble";
}

public String floatRead()
{
return "arrayReadFloat";
}

public String floatWrite()
{
return "arrayWriteFloat";
}

public String intRead()
{
return "arrayReadInt";
}

public String intWrite()
{
return "arrayWriteInt";
}

public String longRead()
{
return "arrayReadLong";
}

public String longWrite()
{
return "arrayWriteLong";
}

public String objectRead()
{
return "arrayReadObject";
}

public String objectWrite()
{
return "arrayWriteObject";
}

public String shortRead()
{
return "arrayReadShort";
}

public String shortWrite()
{
return "arrayWriteShort";
}
}
}

Laden…
Annuleren
Opslaan