Skip to content

Commit

Permalink
Merge pull request #244 from shifujun/redirectMethodCallToStatic
Browse files Browse the repository at this point in the history
add a useful CodeConverter method:redirectMethodCallToStatic
  • Loading branch information
chibash committed Feb 2, 2019
2 parents 6ea8021 + c85bc4f commit 0ac942c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/main/javassist/CodeConverter.java
Expand Up @@ -25,6 +25,7 @@
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;
Expand Down Expand Up @@ -406,6 +407,42 @@ public void redirectMethodCall(String oldMethodName,
= 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
* <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
Expand Down
29 changes: 29 additions & 0 deletions src/main/javassist/convert/TransformCallToStatic.java
@@ -0,0 +1,29 @@
package javassist.convert;

import javassist.CtMethod;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
import javassist.bytecode.Descriptor;
import javassist.bytecode.Opcode;

public class TransformCallToStatic extends TransformCall {
public TransformCallToStatic(Transformer next, CtMethod origMethod, CtMethod substMethod) {
super(next, origMethod, substMethod);
methodDescriptor = origMethod.getMethodInfo2().getDescriptor();
}

@Override
protected int match(int c, int pos, CodeIterator iterator, int typedesc, ConstPool cp) {
if (newIndex == 0) {
String desc = Descriptor.insertParameter(classname, methodDescriptor);
int nt = cp.addNameAndTypeInfo(newMethodname, desc);
int ci = cp.addClassInfo(newClassname);
newIndex = cp.addMethodrefInfo(ci, nt);
constPool = cp;
}
iterator.writeByte(Opcode.INVOKESTATIC, pos);
iterator.write16bit(newIndex, pos + 1);
return pos;
}
}
14 changes: 14 additions & 0 deletions src/test/javassist/JvstTest3.java
Expand Up @@ -586,6 +586,20 @@ public void testMethodRedirect2() throws Exception {
assertEquals(524, invoke(obj, "test"));
}

public void testMethodRedirectToStatic() throws Exception {
CtClass targetClass = sloader.get("test3.MethodRedirectToStatic");
CtClass staticClass = sloader.get("test3.MethodRedirectToStatic2");
CtMethod targetMethod = targetClass.getDeclaredMethod("add");
CtMethod staticMethod = staticClass.getDeclaredMethod("add2");
CodeConverter conv = new CodeConverter();

conv.redirectMethodCallToStatic(targetMethod, staticMethod);
targetClass.instrument(conv);
targetClass.writeFile();
Object obj = make(targetClass.getName());
assertEquals(30, invoke(obj, "test"));
}

public void testClassMap() throws Exception {
ClassMap map = new ClassMap();
map.put("aa", "AA");
Expand Down
22 changes: 22 additions & 0 deletions src/test/test3/MethodRedirectToStatic.java
@@ -0,0 +1,22 @@
package test3;

public class MethodRedirectToStatic {

public static void main(String[] args) {
System.out.println(new MethodRedirectToStatic().test());
}

int add(int a, int b) {
return a + b;
}

public int test() {
return add(1, 2);
}
}

class MethodRedirectToStatic2 {
public static int add2(MethodRedirectToStatic target, int a, int b) {
return target.add(a * 10, b * 10);
}
}

0 comments on commit 0ac942c

Please sign in to comment.