1 Reply Latest reply on Dec 7, 2010 7:55 PM by ahmed.s.mostafa

    VerifyError when invoking a modified method

    ahmed.s.mostafa

      Hello everyone,

      I'm working on a demo for dependency injection automation. My work is divided between creating new classes and modifying an existing class.

       

      The new generated classes are running fine when trying to instantiate them from any new java program I create.

      However, the modified class isn't running and throws the following exception, although I'm able to use the three classes within eclipse; i can browse the methods, I can even decompile them and see to the generated code, it is only a matter of running the main (existing) class:

       

      Exception in thread "main" java.lang.VerifyError: (class: generated/myjseuss/EmailSender, method: sendEmail signature: (Lch/unibnf/scg/sample/model/Email;)V) Bad type in putfield/putstatic

       

      The modifications I do are the following:

      1- create Guice binder instance variable.

      2- create Guice injector instance variable.

      3- add the instance variables (CtField) into the target class.

      4- I have faced some troubles for initializing the objects, only the following approach worked with me:

       

                String constructorSrc = "";
      
                String constructBinder = "dummyBinder" + " = new "
                          + ctGuiceBinder.getName() + "();";
                String constructInjector = "dummyInjector" + " = "
                          + Guice.class.getName()
                          + ".createInjector( new com.google.inject.Module[]{"
                          + "dummyBinder" + "});";
      
                String binderEqual = binderField.getName() + " = dummyBinder;";
                String injectorEqual = injectorField.getName() + " = dummyInjector;";
      
                ctConstructor.addLocalVariable("dummyBinder",
                                    binderField.getType());
                ctConstructor.addLocalVariable("dummyInjector",
                                    injectorField.getType());
                constructorSrc = "{" + constructBinder + constructInjector
                               + "}";
                ctConstructor.insertAfter(constructorSrc);
                constructorSrc = "{" + binderEqual + "\n" + injectorEqual
                               + "};";
                ctConstructor.insertAfter(constructorSrc);
      
      

       

      private static void createConstructor(CtClass ctContainer,
      CtClass ctGuiceBinder, CtField binderField, CtField injectorField)
      throws CannotCompileException, NotFoundException {
      String constructorSrc = "";
      String constructBinder = "dummyBinder" + " = new "
      + ctGuiceBinder.getName() + "();";
      String constructInjector = "dummyInjector" + " = "
      + Guice.class.getName()
      + ".createInjector( new com.google.inject.Module[]{"
      + "dummyBinder" + "});";
      String binderEqual = binderField.getName() + " = dummyBinder;";
      String injectorEqual = injectorField.getName() + " = dummyInjector;";
      CtConstructor[] inits = ctContainer.getConstructors();
      if (inits != null && inits.length > 0) {
      for (CtConstructor ctConstructor : inits) {
      ctConstructor.addLocalVariable("dummyBinder",
      binderField.getType());
      ctConstructor.addLocalVariable("dummyInjector",
      injectorField.getType());
      constructorSrc = "{" + constructBinder + constructInjector
      + "}";
      ctConstructor.insertAfter(constructorSrc);
      constructorSrc = "{" + binderEqual + "\n" + injectorEqual
      + "};";
      ctConstructor.insertAfter(constructorSrc);
      }
      } else {
      String constructorPrefix = "public " + ctContainer.getSimpleName()
      + "(){";
      String constructorSuffix = "}";
      // create a new constructor
      constructorSrc = constructorPrefix + constructBinder
      + constructInjector + constructorSuffix;
      CtConstructor constructor = CtNewConstructor.make(constructorSrc,
      ctContainer);
      ctContainer.addConstructor(constructor);
      }
      }String constructorSrc = "";
      String constructBinder = "dummyBinder" + " = new "
      + ctGuiceBinder.getName() + "();";
      String constructInjector = "dummyInjector" + " = "
      + Guice.class.getName()
      + ".createInjector( new com.google.inject.Module[]{"
      + "dummyBinder" + "});";
      String binderEqual = binderField.getName() + " = dummyBinder;";
      String injectorEqual = injectorField.getName() + " = dummyInjector;";

      5- I'm changing the data type of one of the class instance variables to another interface type; which I then inject its concrete implementation using Guice, as follows:

       

                if (ctField.getType().equals(ctCurrentType)) {
                          ctField.setType(ctNewType);
                          ctContainer.instrument(new NewGuiceExprEditor(ctCurrentType,
                                    ctNewType, injectorField));
                }
      

       

      6- The ExprEditor replaces the "new" expression with the injector's getInstance method, as follows:

                          String replacement = "$_= (" + (ctInterfaceType.getName()) + ")" + injectorField.getName()
                                    + ".getInstance(" + ctInterfaceType.getName()
                                    + ".class);";
      
                          e.replace(replacement);
      

       

       

      As I said earlier, the generated .class files are well accepted by eclipse (Helios), decompiling the .class files (including the above) to Java is also ok and no problems at all when running them.

      I'm using Javassist 3.14.0GA on Windows XP with JDK 1.6

       

      The generated bytecode are attached a long with a demo sample.

       

      I will really appreciate your feedback asap.

       

      NOTE: the sample demo needs Google Guice jars (guice-2.0.jar, aopalliance.jar, guice-assistedinject-2.0.jar)

       

      Your quick response is highly appreciated.

       

      Thanks, Ahmed.