Method
starksm64 Jan 2, 2006 4:31 AMI'm looking at using the CodeConverter.redirectMethodCall(CtMethod, CtMethod) to redirect a jdk5 autobox utility method call such as java.lang.Integer.valueOf(int) to another static utility method as part of a jdk5 to jdk1.4.2 conversion tool, but I'm not seeing the redirect show up. The following is the little test program and associated classes:
package org.jboss.test.weaver;
import java.io.File;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import org.jboss.ant.tasks.retro.AutoboxCodeConverter;
import javassist.bytecode.ClassFile;
import javassist.CtClass;
import javassist.ClassPool;
public class WeaverTestCase
{
public static void main(String[] args)
throws Exception
{
File inputFile = new File("/cvs/JBossHead/jbossretro/output/test-classes/org/jboss/test/weaver/AutoboxUsage.class");
DataInputStream is = new DataInputStream(new FileInputStream(inputFile));
ClassFile inputCF = new ClassFile(is);
is.close();
CtClass clazz = ClassPool.getDefault().get(inputCF.getName());
clazz.instrument(new AutoboxCodeConverter());
File outputFile = new File("/cvs/JBossHead/jbossretro/output/test-classes14/org/jboss/test/weaver/AutoboxUsage.class");
FileOutputStream os = new FileOutputStream(outputFile);
DataOutputStream dos = new DataOutputStream(os);
inputCF.write(dos);
dos.close();
}
package org.jboss.test.weaver;
import java.util.ArrayList;
// Sample autobox usage
public class AutoboxUsage
{
public static void main(String[] args)
{
ArrayList<Integer> ial = new ArrayList<Integer>();
for(int i = 1; i <= 10; i ++)
ial.add(i);
if(ial.get(0) == 1);
System.out.println("iol(0) == 1 as expected");
}
}
package org.jboss.ant.tasks.retro;
import javassist.CannotCompileException;
import javassist.CodeConverter;
import javassist.CtClass;
import javassist.ClassPool;
import javassist.NotFoundException;
import javassist.CtMethod;
// Registers the Integer.valueOf(int) to AutoboxCodeConverter.valueOf(int) redirect
public class AutoboxCodeConverter extends CodeConverter
{
public AutoboxCodeConverter()
throws NotFoundException, CannotCompileException
{
ClassPool defaultPool = ClassPool.getDefault();
CtClass integerClass = defaultPool.get("java.lang.Integer");
CtClass intClass = defaultPool.get("int");
CtClass[] intSig = {intClass};
CtClass autoboxClass = defaultPool.get("org.jboss.ant.tasks.retro.AutoboxCodeConverter");
CtMethod valueOfInt2 = autoboxClass.getDeclaredMethod("valueOf", intSig);
CtMethod valueOfInt = integerClass.getDeclaredMethod("valueOf", intSig);
System.out.println("redirecting: "+valueOfInt+" to: "+valueOfInt2);
redirectMethodCall(valueOfInt, valueOfInt2);
}
public static Integer valueOf(int i)
{
return new Integer(i);
}
}
javap -verbose on the resulting output/test-classes14/org/jboss/test/weaver/AutoboxUsage.class is still showing an "invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;" rather than the desired invokestatic on the AutoboxCodeConverter.valueOf(int) method:
Compiled from "AutoboxUsage.java"
public class org.jboss.test.weaver.AutoboxUsage extends java.lang.Object
SourceFile: "AutoboxUsage.java"
minor version: 0
major version: 48
Constant pool:
const #1 = Method #13.#33; // java/lang/Object."<init>":()V
const #2 = class #34; // java/util/ArrayList
const #3 = Method #2.#33; // java/util/ArrayList."<init>":()V
const #4 = Method #7.#35; // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
const #5 = Method #2.#36; // java/util/ArrayList.add:(Ljava/lang/Object;)Z
const #6 = Method #2.#37; // java/util/ArrayList.get:(I)Ljava/lang/Object;
const #7 = class #38; // java/lang/Integer
const #8 = Method #7.#39; // java/lang/Integer.intValue:()I
const #9 = Field #40.#41; // java/lang/System.out:Ljava/io/PrintStream;
const #10 = String #42; // iol(0) == 1 as expected
const #11 = Method #43.#44; // java/io/PrintStream.println:(Ljava/lang/String;)V
const #12 = class #45; // org/jboss/test/weaver/AutoboxUsage
const #13 = class #46; // java/lang/Object
const #14 = Asciz <init>;
const #15 = Asciz ()V;
const #16 = Asciz Code;
const #17 = Asciz LineNumberTable;
const #18 = Asciz LocalVariableTable;
const #19 = Asciz this;
const #20 = Asciz Lorg/jboss/test/weaver/AutoboxUsage;;
const #21 = Asciz main;
const #22 = Asciz ([Ljava/lang/String;)V;
const #23 = Asciz i;
const #24 = Asciz I;
const #25 = Asciz args;
const #26 = Asciz [Ljava/lang/String;;
const #27 = Asciz ial;
const #28 = Asciz Ljava/util/ArrayList;;
const #29 = Asciz LocalVariableTypeTable;
const #30 = Asciz Ljava/util/ArrayList<Ljava/lang/Integer;>;;
const #31 = Asciz SourceFile;
const #32 = Asciz AutoboxUsage.java;
const #33 = NameAndType #14:#15;// "<init>":()V
const #34 = Asciz java/util/ArrayList;
const #35 = NameAndType #47:#48;// valueOf:(I)Ljava/lang/Integer;
const #36 = NameAndType #49:#50;// add:(Ljava/lang/Object;)Z
const #37 = NameAndType #51:#52;// get:(I)Ljava/lang/Object;
const #38 = Asciz java/lang/Integer;
const #39 = NameAndType #53:#54;// intValue:()I
const #40 = class #55; // java/lang/System
const #41 = NameAndType #56:#57;// out:Ljava/io/PrintStream;
const #42 = Asciz iol(0) == 1 as expected;
const #43 = class #58; // java/io/PrintStream
const #44 = NameAndType #59:#60;// println:(Ljava/lang/String;)V
const #45 = Asciz org/jboss/test/weaver/AutoboxUsage;
const #46 = Asciz java/lang/Object;
const #47 = Asciz valueOf;
const #48 = Asciz (I)Ljava/lang/Integer;;
const #49 = Asciz add;
const #50 = Asciz (Ljava/lang/Object;)Z;
const #51 = Asciz get;
const #52 = Asciz (I)Ljava/lang/Object;;
const #53 = Asciz intValue;
const #54 = Asciz ()I;
const #55 = Asciz java/lang/System;
const #56 = Asciz out;
const #57 = Asciz Ljava/io/PrintStream;;
const #58 = Asciz java/io/PrintStream;
const #59 = Asciz println;
const #60 = Asciz (Ljava/lang/String;)V;
{
public org.jboss.test.weaver.AutoboxUsage();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 16: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lorg/jboss/test/weaver/AutoboxUsage;
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=3, Args_size=1
0: new #2; //class java/util/ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: iconst_1
9: istore_2
10: iload_2
11: bipush 10
13: if_icmpgt 31
16: aload_1
17: iload_2
18: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
21: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
24: pop
25: iinc 2, 1
28: goto 10
31: aload_1
32: iconst_0
33: invokevirtual #6; //Method java/util/ArrayList.get:(I)Ljava/lang/Object;
36: checkcast #7; //class java/lang/Integer
39: invokevirtual #8; //Method java/lang/Integer.intValue:()I
42: iconst_1
43: if_icmpne 46
46: getstatic #9; //Field java/lang/System.out:Ljava/io/PrintStream;
49: ldc #10; //String iol(0) == 1 as expected
51: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
54: return
LineNumberTable:
line 20: 0
line 21: 8
line 22: 16
line 21: 25
line 24: 31
line 25: 46
line 26: 54
LocalVariableTable:
Start Length Slot Name Signature
10 21 2 i I
0 55 0 args [Ljava/lang/String;
8 47 1 ial Ljava/util/ArrayList;
LocalVariableTypeTable: length = 0xC
00 01 00 08 00 2F 00 1B 00 1E 00 01
}
Is the CodeConverter.redirectMethodCall the correct way to try to do this?