0 Replies Latest reply on Jan 2, 2006 4:31 AM by Scott Stark

    Method

    Scott Stark Master

      I'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?