1 Reply Latest reply on Feb 8, 2008 3:57 PM by arsami

    javassist.CannotCompileException: by java.lang.LinkageError:

    arsami

      Hi,

      I am trying to change a class on-the-fly with this small program:

       Hello h = new Hello();
       h.say();
       ClassPool cp = new ClassPool(true);
       CtClass cc = cp.get("com.blabla.test.Hello");
       CtMethod m = cc.getDeclaredMethod("say");
       m.insertBefore("{ System.out.println(\"Hello.say():\"); }");
       Class c = cc.toClass();
       h = (Hello)c.newInstance();
       h.say();


      and I get the following exception:

      javassist.CannotCompileException: by java.lang.LinkageError: duplicate class definition:
       at javassist.ClassPool.toClass(ClassPool.java:953)
       at javassist.ClassPool.toClass(ClassPool.java:896)
       at javassist.ClassPool.toClass(ClassPool.java:854)
       at javassist.CtClass.toClass(CtClass.java:1053)
       at com.blabla.test.PlainTester.testMethodInjection(PlainTester.java:32)
      
      Caused by: java.lang.LinkageError: duplicate class definition: com/blabla/test/Hello
       at java.lang.ClassLoader.defineClass1(Native Method)
       at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
       at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at javassist.ClassPool.toClass2(ClassPool.java:965)
       at javassist.ClassPool.toClass(ClassPool.java:947)
       ... 6 more


      Of course, if I don't use the Hello class before injecting that method, it works fine. All the sample programs that I found on the net are showing a method injection without any prior use. However, my requirement is that, I have to be able to change a class while the system is running.

      Is there any way that we can do that?

      Your help is greatly appreciated...


        • 1. Re: javassist.CannotCompileException: by java.lang.LinkageEr
          arsami

          Here is what I found about this issue:

          1- there is a name for this on-the-fly change, it is called Class Reloading in Java

          2- By default, Class Reloading is not supported by Java. However, you may use Java Platform Debugger Architecture (JPDA) to reload a class.

          3- Javassist has a class for this, it's called HotSwapper

          4- Another way to reload a class in runtime is to use a different ClassLoader instance. However, it is almost impossible to do this if your application is running in a Java Application Server or Web Server. You can simply mess with your server's internal ClassLoader.

          ----

          By the way, the main reason for doing this was that I would like to be able to turn on/off logging and auditing of my Web application by method injection without needing to restart the server.

          If any one knows a different approach, I will really appreciate if you could it share it.

          Thanks!