1 Reply Latest reply on Mar 30, 2010 2:54 AM by ericjava

    Saving proxy classes and using them in Android

      I am new to the wonderful world of Javassist, and I now have a question:

       

      I have used the very easy and convenient ProxyFactory in the usual way:

       

      final ProxyFactory proxyFactory = new ProxyFactory();
              proxyFactory.writeDirectory = "/tmp";
              proxyFactory.setSuperclass(Invoice.class);
              final MethodHandler methodHandler = new MethodHandler() {

       

                  public Object invoke(Object self, Method m, Method proceed,
                          Object[] args) throws Throwable {
                      System.out.println("Name: " + m.getName());
                      return proceed.invoke(self, args);  // execute the original method.
                  }
              };
              proxyFactory.setFilter(new MethodFilter() {

                  public boolean isHandled(Method m) {
                      // ignore finalize()
                      return !m.getName().equals("finalize");
                  }
              });
              final Class klass = proxyFactory.createClass();
              Invoice invoice = (Invoice) klass.newInstance();
              ((ProxyObject) invoice).setHandler(methodHandler);

       

      That works great.  When I call methods on the invoice object there, I immediately see that my MethodHandler is invoked.  Super-cool!

       

      Also, it does one more thing: it saves a new class file, with a name like Invoice_$$_javassist_0.class .

       

      I noticed on the documentation of ProxyFilter.writeDirectory, it says that that is "for debugging".  Hmm.

       

      What I would like to do is be able to use that generated class, without needing to have the bytecode present.  The reason for this is I want to use it within Android, and Android doesn't use regular class files.  If I can use the ProxyFactory to write out the class files, then I can build my Android DEX files using those class files.  But I don't know how to load or make use of the generated files like Invoice_$$_javassist_0.class.

       

      Does my question make sense?  I assume that ProxyFactory is able to save those class files for a good reason, but I can't find out how to make use of them.

       

      Thanks

        • 1. Re: Saving proxy classes and using them in Android

          I answer my own question.

           

          It looks like Javassist isn't the right tool for this.  It needs to mess with classloaders, an area where Android is quite different from standard Java.

           

          I got it done with ASM.  ASM was perfect for this.  It lets me modify the class itself, rather than creating a proxy for it.  That's (slightly) better for performance, and also makes it very easy to use them with the rest of the Android packaging tools.Also it has more flexibility.  The class can be final, doesn't need a no-args constructor, etc.

           

          The hard part about ASM were two things:

           

          • It's a bit of an API to deal with.
          • The new code I insert had to be Java assembly

           

          But there's a trick that made it easier to get the assembly code.  There's a ASMifier tool that generates ASM API calls to generate a given class file.  So you just write the code you want, run ASMifier on it, and cut and paste the assembly generator calls.  But doing anything more than small amounts of code would be a big pain IMO.

           

          Anyway, both are impressive tools, but ASM was the right one for this job.