4 Replies Latest reply on Aug 22, 2004 9:21 AM by Shigeru Chiba

    bug in ExprEditor.edit(NewExpr call) when in try-catch-block

    fedor w Newbie

      I'm using java-assist to rewrite code using ExprEditor and NewExpr.replace(). When my code looks like this:

      HashMap h=new HashMap(size);
      it has to be converted to
      HashMap h=new HashMapWrapper(size,some_extra_params);

      The wrapper is not a real wrapper, but just extends the real HashMap.
      Everything works fine, but the byte code is screwed up when trying
      to patch:

      try
      {
      HashMap h=new HashMap(size);
      }
      catch (Exception e)
      {
      //
      }

      Something goes wrong with the try-block (I already tried the latest source from CVS). When I 'm trying to decompile the try block is just gone; it can't even decompile properly.

      The strange thing is that this only happens when the constructor call (NewExpr) is the FIRST call in a try-block.

      So, this works perfectly:

      try
      {
      String blah="blah";
      HashMap h=new HashMap(size);
      }
      catch (Exception e)
      {
      //
      }

      It looks like a bug...


        • 1. Re: bug in ExprEditor.edit(NewExpr call) when in try-catch-b
          Shigeru Chiba Expert

          I ran the following test case but any problem was not found:

          ExprEditor ed = new ExprEditor() {
           public void edit(NewExpr expr) throws CannotCompileException {
           expr.replace("$_ = new test2.HashMapWrapper($1, 1);");
           }
          };
          
          CtClass cc = ClassPool.getDefault().get("NewExprInTry");
          CtMethod m1 = cc.getDeclaredMethod("foo");
          m1.instrument(ed);
          cc.writeFile();
          


          The definitions of NewExprInTry is:

          class HashMapWrapper extends HashMap {
           HashMapWrapper(int size, int args) {
           super(size);
           }
          }
          
          public class NewExprInTry {
           public int foo(int size) {
           HashMap h;
           try {
           h = new HashMap(size);
           }
           catch (Exception e) {}
           return 1;
           }
          }
          


          Could you post a test case?

          • 2. Re: bug in ExprEditor.edit(NewExpr call) when in try-catch-b
            Shigeru Chiba Expert

            I'm using JDK1.4.2 and the javac compiler of 1.4.
            What are you using?

            • 3. Re: bug in ExprEditor.edit(NewExpr call) when in try-catch-b
              fedor w Newbie

               

              // code to patch class-file:
              
              import javassist.*;
              import javassist.expr.*;
              import java.io.*;
              import java.util.*;
              public class Patch
              {
               public static void main(String args[])
               throws Exception
               {
               File f=new File(args[0]);
               FileInputStream fis=new FileInputStream(f);
               ClassPool cp=new ClassPool();
               cp.appendSystemPath();
               CtClass c=cp.makeClass(fis);
               c.instrument(
               new ExprEditor()
               {
               public void edit(NewExpr call)
               throws CannotCompileException
               {
               if ("java.util.ArrayList".equals(call.getClassName()))
               {
               call.replace("$_=new ArrayListWrapper(\"hi there\",$$);")
              ;
               }
               }
               });
               c.writeFile("patched");
               c.detach();
               fis.close();
               }
              }
              
              // the wrapper:
              
              public class ArrayListWrapper extends java.util.ArrayList
              {
               public ArrayListWrapper(String bla,int size)
               {
               }
               public ArrayListWrapper(String bla)
               {
               }
              }
              
              // class to patch:
              
              import java.util.*;
              public class Test
              {
               public static void test()
               {
               try
               {
               ArrayList h=new ArrayList();
               }
               catch (Exception e)
               {
               e.printStackTrace();
               }
               }
               public static void main(String args[])
               {
               test();
               }
              }


              When I run Patch on Test.class and decompile the created Test.class jad complains:

              Parsing Test.class...Overwrite Test.jad [y/n/a/s] ? y
              Generating Test.jad
              Couldn't fully decompile method test
              Couldn't resolve all exception handlers in method test

              Perhaps I'm relying on jad too much... the class seems to work, but the strange thing is, that jad does not complain when puting somehting (which will not be removed by the optimizer :)) before the new ArrayList statement in my Test-class.

              What I'm seeing now is that the code, which cannot be decompiled by jad, seems to run. Maybe I should forget about jad :)

              I saw this at work when trying to patch some class-files compiled by some jdk from IBM (1.3). The problem described above occured during patching a class which contains a couple of nop's in the byte-code at the beginning of bytecode of a method like the one in Test.class. Perhaps that was the problem...I'm still not sure. I got VerifyErrors and even Web$phere-crashes, but that's regular stuff :)

              I'm still not sure about this. Perhaps it's a problem of jad, but I've never had any problems with jad.

              I'm using Sun's JDK 1.4.1_03 on Linux. At work it's 1.3 on Window$. Same behavior.



              • 4. Re: bug in ExprEditor.edit(NewExpr call) when in try-catch-b
                Shigeru Chiba Expert

                Since the code modified by Javassist did not look like code
                generated by javac, jad might have been confused. I don't
                think jad can decompile all kinds of correct java bytecode.

                If you have time at work, I would like to ask you to run the same code
                on IBM JDK, which might include IBM's own Java compiler.