1 2 Previous Next 22 Replies Latest reply on Jul 28, 2004 6:18 AM by chiba Go to original post
      • 15. Re: classloaders, loading classes dynamically
        chiba

        Good.

        Of course two thing had to be made: injecting user classpath
        and container's classloader


        What the user class path and the container's class loader should be
        given to Javassist depends on the underlaying platform. I could not
        come up with an idea to automatically detect them.

        Anyway, thank you for your contribution.

        • 16. Re: classloaders, loading classes dynamically
          budevik

           

          "chiba" wrote:
          Good.
          What the user class path and the container's class loader should be
          given to Javassist depends on the underlaying platform. I could not
          come up with an idea to automatically detect them.


          the most elegant solution I can imagine now is to pass any object from user's code (i.e. jsp, servlet etc) even like in my case, AOP machine object (beacuse I have to instance it with 'new' in fact) and framework just sets itself with grabbed classpath and class loader (of course this object must be from user's space, I guess that passing i.e. session or response object would fail, because those are container objects).
          anyway now every object intrumented or not is able to load
          I checked Tomcat , but I suppose in JBoss it makes no diffrence.

          Anyway, thank you for your contribution.


          no problem. javassist freed me from proxy based aop limitations. now my code is simple and clean. i'm just "switching" to new approach :)


          • 17. Re: classloaders, loading classes dynamically
            batoussa

            Well done Mr Chiba ! It works ... except for the classpath of course, but it doesn't matter in my app, I can manage it.

            • 18. Re: classloaders, loading classes dynamically
              batoussa

              Hi ,

              I know that it is not the right place to ask this question but I'm sure you've got the solution.

              I'd like to know if it is possible to load a class that is already loaded or to remove from the classloader a loaded class ?

              Indeed, I've got 3 classes with the same name and prototypes (methods ...) but not in the same package.
              So I'd like to load the class dynamically, depends on a property files which inform the package.
              So, the first time I load class a.Bat (and change the name to b.Bat), it works. But the next time, if I try to load c.Bat, I've got an LinkageError, which means that the class is already loaded, BUT i don't need the loaded class anymore.

              Thanks for your suggestion, and sorry again to post it here.

              • 19. Re: classloaders, loading classes dynamically
                chiba

                 

                I'd like to know if it is possible to load a class that is already
                loaded or to remove from the classloader a loaded class ?


                No at least with the JDK 1.4 or 1.5. If you use JPDA (debugger API),
                you can dynamically reload a class but there are some limitations
                with respect to differences between the versions of that class.

                However, I cannot understand why you got LinkageError when you
                loaded c.Bat. Is "c" a package name? If yes, c.Bat is a different class
                from a.Bat and b.Bat. I suppose that your program (a.Bat or b.Bat)
                accidentally had been linked with an older version of c.Bat.


                • 20. Re: classloaders, loading classes dynamically
                  batoussa

                   

                  However, I cannot understand why you got LinkageError when you
                  loaded c.Bat. Is "c" a package name? If yes, c.Bat is a different class
                  from a.Bat and b.Bat. I suppose that your program (a.Bat or b.Bat)
                  accidentally had been linked with an older version of c.Bat.


                  Yeah, sorry I made a mistake, I meant c.Bat where I change the name to b.Bat. So there were already a b.Bat class in the class loader.

                  Have you got any solution with jdk1.4 at least ?

                  • 21. Re: classloaders, loading classes dynamically
                    batoussa

                    Here is my ClassLoader :

                    package loader;
                    
                    import java.io.FileInputStream;
                    import java.io.IOException;
                    import java.util.Properties;
                    
                    import javassist.CannotCompileException;
                    import javassist.ClassPool;
                    import javassist.CtClass;
                    import javassist.NotFoundException;
                    
                    /**
                     * @author Batoussa Mougamadou
                     */
                    public class MyClassLoader extends ClassLoader {
                    
                     private final ClassPool originalPool = ClassPool.getDefault();
                     ////////////////
                    
                     public String getPackage() {
                     try {
                     FileInputStream in = new FileInputStream("file.properties");
                     Properties prop = new Properties();
                    
                     // load all
                     prop.load(in);
                    
                     in.close();
                     return prop.getProperty("package");
                     } catch (Exception e) {
                     e.printStackTrace();
                     return null;
                     }
                     }
                    
                     public Class loadClass(String className, boolean resolveIt)
                     throws ClassNotFoundException {
                     return super.loadClass(className, resolveIt);
                     }
                    
                     private Class loadClass(byte[] b, String className) {
                     //override classDefine (as it is protected) and define the class.
                     Class clazz = null;
                     try {
                     ClassLoader loader = ClassLoader.getSystemClassLoader();
                    
                     Class cls = Class.forName("java.lang.ClassLoader");
                    
                     // CALL FIND LOADED CLASS
                     java.lang.reflect.Method method =
                     cls.getDeclaredMethod("findLoadedClass", new Class[] { String.class });
                     method.setAccessible(true);
                     Object[] args = new Object[] { className };
                     clazz = (Class) method.invoke(loader, args);
                     method.setAccessible(false);
                    
                     if( clazz != null )
                     return clazz;
                     else System.out.println("CLASS NOT BEEN LOADED");
                    
                     // CALL DEFINE CLASS
                     method = cls.getDeclaredMethod( "defineClass", new Class[] { String.class, byte[].class, int.class, int.class });
                    
                     // protected method invocaton
                     method.setAccessible(true);
                     args = new Object[] { className, b, new Integer(0), new Integer(b.length)};
                     clazz = (Class) method.invoke(loader, args);
                     method.setAccessible(false);
                    
                     } catch (Exception e) {
                     e.printStackTrace();
                     System.exit(1);
                     }
                     return clazz;
                     }
                    
                     private ClassPool pool;
                    
                     public MyClassLoader() throws NotFoundException {
                     pool = new ClassPool();
                     pool.insertClassPath("."); // MyApp.class must be there.
                     }
                    
                     /* Finds a specified class.
                     * The bytecode for that class can be modified.
                     */
                     public Class findClass(String name) throws ClassNotFoundException {
                     try {
                     // Set the class path
                     pool.appendClassPath("C:/Program Files/eclipse/workspace/WebClassLoader/WEB-INF/lib/bat.jar");
                     CtClass cc = pool.get(getPackage()+"."+name);
                     // Change the name of the class
                     cc.setName("b." + name);
                     return loadClass(cc.toBytecode(), "b." + name);
                     } catch (NotFoundException e) {
                     throw new ClassNotFoundException();
                     } catch (IOException e) {
                     throw new ClassNotFoundException();
                     } catch (CannotCompileException e) {
                     throw new ClassNotFoundException();
                     }
                     }
                    }
                    


                    • 22. Re: classloaders, loading classes dynamically
                      chiba

                      Maybe the only solution is to use JPDA.

                      Otherwise, if feasible, you should make
                      a new child class loader for loading your app.
                      and reload your app. from scratch
                      whenever the config file is updated.
                      However, this solution discards all existing objects
                      when the config is updated.

                      1 2 Previous Next