14 Replies Latest reply: May 6, 2004 4:12 PM by Jwahar Bammi RSS

    javassist.ClassPool should extend the ClassLoader or URLClas

    jesper mortensen Newbie

      Dear Javassist Users and Developers

      Thank you for an excellent tool

      A suggestion:

      I have tried using Javassist to make a tool for Tomcat and it seems to me that the ClassPool as a sideeffect og its purpose of keeping the classes together, really is a ClassLoader that caches loaded (and modified) classes.

      Tomcat (and other J2EE servers) uses a hierarki of ClassLoaders and you should be able to plug the ClassPool directly in to this hierarki

      If ClassPool extended the WebappClassLoader from Tomcat it would fit directly in (but it would probably be getting to close to Tomcat).
      Extending URLClassLoader should be close enough to only force minor rewrites in the Tomcat classes to get the full functionality

      jesper mortensen

        • 1. Re: javassist.ClassPool should extend the ClassLoader or URL
          Shigeru Chiba Expert

          Your suggestion is right.
          My current plan is to make it possible to
          a hierarchy of ClassPool parallel
          to ClassLoader's.

          • 2. Re: javassist.ClassPool should extend the ClassLoader or URL
            jesper mortensen Newbie

            Sounds like a good idea

            I ended up making a custom classloader inheriting ..catalina..WebappClassLoader only overriding a method "findResourceInternal" in WebappClassLoader, and then exchanging the loaded bytecode with bytecode loaded by ClassPool (and then modfied).

            The WebappLoader (container) makes a cast somewhere so even if the documentation states that you can define your own classloader, for now the only way to do it is to inherit WebappClassLoader.

            To make this work I had to give ClassPool the path from the whole classloader Hierarky, potentially mixing different sources for the code loaded by the original hierarky and ClassPool.
            (And loading the class twice not very efficient, I think that I can find a way around this)

            What would make this work was that I could tell Classpool to use my new class as ClassLoader, it would then be up to me to (re)place the modfied class in the inherited ClassLoaders internal repository.

            By using this structure you would not need to make ClassPool aware of the hierarky. And it would be up to my class to choose between delegating "upwards" or loading fom my own classpath.




            • 3. Re: javassist.ClassPool should extend the ClassLoader or URL
              Bill Burke Master

              We have the same issue with JBoss classloaders. This becomes even more of a pain when jBoss hot deployment comes into play.

              • 4. Re: javassist.ClassPool should extend the ClassLoader or URL
                jesper mortensen Newbie

                I think a general solution could be letting the ClassPool implement some sort of listener listening for "ClassLoadEvent"s

                The ClassLoader should then be able to accept listeners and make synchronous calls to the listeners when loading a class. The registering could be with some sort of Regex String for filtering classes.

                A ClassLoadEvent could have the the byte[] in the "ClassLoadEvent" (maybe alert a Translator) modify the classes and return the modfied bytecode in the event.

                The ClassLoader would then call defineClass() and resolve() on the modied class and cache it internally.

                To make this work in a concrete J2EE server the person implementing this would have some skeleton code to subclass the J2EE servers ClassLoader with

                • 5. Re: javassist.ClassPool should extend the ClassLoader or URL
                  Scott Stark Master

                  This needs to be integrating with something like the JDK 1.5 java.lang.instrument.ClassFileTransformer, not by requiring subclasses of the app server class loader.

                  byte[] transform(ClassLoader loader,
                   String className,
                   Class classBeingRedefined,
                   ProtectionDomain protectionDomain,
                   byte[] classfileBuffer)
                   throws IllegalClassFormatException;
                  


                  The app server class loaders should be able to evolve independent of the aop layer. There has to be a non-intrusive api for integrating the aop class generation provided by the app server.

                  • 6. Re: javassist.ClassPool should extend the ClassLoader or URL
                    Bill Burke Master

                    Unfortunately, AFAIK, the JDK 1.5 ClassFileTransformer is only available in Debug mode and should not be used for what we want to use it for. This is what Jonas Boner and Alex Vasseur of AspectWerkz told me at the AOSD conference.

                    Bill

                    • 7. Re: javassist.ClassPool should extend the ClassLoader or URL
                      Scott Stark Master

                      So it needs to be done above the JDK. I'm simply referring to this api as the type of contract that is needed.

                      • 8. Re: javassist.ClassPool should extend the ClassLoader or URL
                        jesper mortensen Newbie

                        But above the JDK in the API means letting the ClassLoader implement something like the java.lang.instrument.Instrumentation interface

                        By having the standard classloaders used by the server in normal mode as default, and then suclassing them with an implementation of the interface, it could be a configuration option if an application should instantiate with the subclass

                        The filtering and the potentially "slow" syncronous call to java.lang.instrument.ClassFileTransformer (ClassPool) would only be active if the subclass is used

                        In this way the AOP would only be able to modify classes in their own context and the ClassLoader hierarky would be intact

                        • 9. Re: javassist.ClassPool should extend the ClassLoader or URL
                          Scott Stark Master

                          No, the class loader repository would have to provide support for this, and we already have an interface for this associated with the org.jboss.util.loading.Translator which is associated with the loader repository and optionally used by the class loader if present. AOP is not the only framework that may want to do byte code manipulation, so there has to be a general mechanism not tied to AOP.

                          Further, subclassing the class loaders is very problematic due to the deadlock problems caused by the private synchronized Class loadClassInternal(String name) method in ClassLoader. Look at the org.jboss.mx.loading classes for the hoops that have to be jumped through to implement the default flat class loading model for example.

                          • 10. Re: javassist.ClassPool should extend the ClassLoader or URL
                            jesper mortensen Newbie

                            Just being a pest ..

                            Ok looking at org.jboss.mx.loading I can see that a lot of work has gone into making classloading work in jboss.
                            Javassist beeing a subproject of jboss should of course respect the jboss strategies.

                            But still it seems to me that it would make sense to have a general way to make ClassPool plug in to an existing classloader hierarky

                            In Tomcat they have chosen to make a reimplementation of the functionalities of URLClassLoader (maybe to avoid some internal problems in URLClassLoader/ClassLoader) and as it is a userdefined classloader has to inherit WebappClassLoader (therefore you cannont give it javaassist.Loader as a userdefined classloader). In some other J2EE servers there might be other specialities.

                            The basic problem beeing that the only way to get the classes you want to manipulate into ClassPool is by setting the classPath, any structure that makes ClassPoll use an existing classloader (for finding/loading classes, and for compiling and later defining classes) would be a step towards a generic solution.

                            • 11. Re: javassist.ClassPool should extend the ClassLoader or URL
                              Shigeru Chiba Expert

                              Ok, I understand your suggestion is that we should improve
                              the perforamance of ClassPool.makeClass(InputStream)
                              and javassist.ByteArrayClassPath. These are for feeding a
                              byte array to ClassPool. It should be a general framework
                              for integrating your own ClassLoader and Javassist.

                              Of course, these have not been tuned very well compared
                              to the standard ClassPath stuff, but I think it is possible to
                              make them faster.

                              • 12. Re: javassist.ClassPool should extend the ClassLoader or URL
                                Jwahar Bammi Newbie

                                jesper (jbm4ever)
                                if its possible could you share your Tomcat code example (or a outline). i have been planning to try this with Tomcat and this would be very helpful.
                                thanks
                                bammi@memento-inc.com

                                • 13. Re: javassist.ClassPool should extend the ClassLoader or URL
                                  jesper mortensen Newbie

                                  Sorry for responding so late I thought the issue was dead

                                  I am not really proud of my coding skills and i am working my way throug commenting the code by you can find my classloader at:

                                  http://catspeed.sourceforge.net

                                  As catspeedCL.jar (in catspeed.tar.gz) which includes source code

                                  I have tried solving the plugin problem by recursing through the classloading hierarky by building a classpath for classpool that should behave somewhat like being "plugged in" (that means taking the classes in the "reverse order" nearest the bottom of the hierarky except for system classes)
                                  this reverse ordering being a servletcontainer feature et seems

                                  • 14. Re: javassist.ClassPool should extend the ClassLoader or URL
                                    Jwahar Bammi Newbie

                                    Thanks very much: appreciate you sharing your code and for responding.
                                    cheers,
                                    Jwahar Bammi