java javassist.CannotCompileException: by java.lang.LinkageError: loader

Sergey Solomevich

I need to change the method (calculation formula) without recompiling the application. I know that this can be done with the help of javassist. So far I'm trying on a simple example. In the post method, I call the createMethodHelper () method, which must change the Helper2 method. All OK. But after a repeated call (reloading the page), the error javassist.CannotCompileException: by java.lang.LinkageError: loader So, the class containing the only method I want to change

package ru.testScandJavaCafee.controller;

public class Helper2 {
public String createList()
    {
        System.out.println("++++");
        return "1000";
    }
}

And the class from which I change the method

public String createMethodHelper() throws NotFoundException, CannotCompileException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, InstantiationException, ClassNotFoundException {

        ClassPool pool = ClassPool.getDefault();
pool.insertClassPath(new ClassClassPath(this.getClass()));
        CtClass cc = pool.get("ru.testScandJavaCafee.controller.Helper2");
        cc.defrost();
        CtMethod cm = cc.getMethod("createList","()Ljava/lang/String;" );
        cc.defrost();
        cm.setBody( "{  return \"300 \" ;}" );

        cc.defrost();
        Class c = cc.toClass();
        cc.defrost();
ru.testScandJavaCafee.controller.Helper2 test = (ru.testScandJavaCafee.controller.Helper2) c.newInstance();
        String sum = test.createList();

        return sum;
    }

After a second call (reloading the page), the error

javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of  org/apache/catalina/loader/WebappClassLoader): attempted  duplicate class definition for name: "ru/testScandJavaCafee/controller/Helper2"
    at javassist.ClassPool.toClass(ClassPool.java:1085)
    at javassist.ClassPool.toClass(ClassPool.java:1028)
    at javassist.ClassPool.toClass(ClassPool.java:986)
    at javassist.CtClass.toClass(CtClass.java:1110)
    at ru.testScandJavaCafee.controller.CoffeeTypeController.createMethodHelper(CoffeeTypeController.java:108)
    at ru.testScandJavaCafee.controller.CoffeeTypeController.doPost(CoffeeTypeController.java:56)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:452)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1087)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.LinkageError: loader (instance of  org/apache/catalina/loader/WebappClassLoader): attempted  duplicate class definition for name: "ru/testScandJavaCafee/controller/Helper2"
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at javassist.ClassPool.toClass2(ClassPool.java:1098)
    at javassist.ClassPool.toClass(ClassPool.java:1079)
    ... 27 more

help to understand how to fix the error

tima

I did some research on this from the documentation and this tutorial. And if you want to modify the method multiple times, you can do it this way:

public static void main(String[] args) {
    try {
        // get a new instance of version 1
        Object newClassInstance1 = m2("com.tima.Helper2", "public String createList() { System.out.println(\"++++\"); return \"200\";}");
        Method method1 = newClassInstance1.getClass().getMethod("createList");

        // this executes the createList in the new class com.tima.Helper2
        String sum1 = (String) method1.invoke(newClassInstance1);
        System.out.println("com.tima.Helper2: " + sum1);

        // this shows that the original Helper method was not modified
        Helper h = new Helper();
        System.out.println("com.tima.Helper: " + h.createList());

        // this shows that the com.tima.Helper2 overrides Helper and can be used as Helper with a modified method
        Helper h2 = (Helper) newClassInstance1;
        System.out.println("com.tima.Helper2 as Helper: " + h2.createList());

        // below does the same thing a second time

        Object newClassInstance2 = m2("com.tima.Helper3", "public String createList() { System.out.println(\"++++\"); return \"300\";}");
        Method method2 = newClassInstance2.getClass().getMethod("createList");
        String sum2 = (String) method2.invoke(newClassInstance2);
        System.out.println("com.tima.Helper3: " + sum2);

        Helper h3 = new Helper();
        System.out.println("com.tima.Helper: " + h3.createList());

        Helper h4 = (Helper) newClassInstance2;
        System.out.println("com.tima.Helper3 as Helper: " + h4.createList());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static Object m2(String className, String methodBody) 
        throws CannotCompileException, InstantiationException, IllegalAccessException, NotFoundException {
    // get the pool
    ClassPool classPool = ClassPool.getDefault();

    // this seems optional, but if it isn't Main.class (my test class) should be replaced with this.getClass()
    classPool.insertClassPath(new ClassClassPath(Main.class));

    // get the helper class
    CtClass helperClass = classPool.get("com.tima.Helper");

    // create a new class
    CtClass newCtClass = classPool.makeClass(className);

    // make it  child of Helper
    newCtClass.setSuperclass(helperClass);

    // this overrides the method in Helper
    newCtClass.addMethod(CtNewMethod.make(methodBody, newCtClass));

    // get a new instance
    Class<?> newClass = newCtClass.toClass();
    Object newClassInstance = newClass.newInstance();

    return newClassInstance;
}

Output

++++
com.tima.Helper2: 200
++++
com.tima.Helper: 1000
++++
com.tima.Helper2 as Helper: 200
++++
com.tima.Helper3: 300
++++
com.tima.Helper: 1000
++++
com.tima.Helper3 as Helper: 300

Basically, everytime you call that method it creates a new class, makes the Helper class its superclass and overrides the createList method. The obvious problem here is depending on how many times you call this method you can wind up with a lot of generated classes. So you may want to add checking of if these class are already loaded before creating.

You say that this method runs when you refresh / load the page so if you just want it to run once, I suggest you put this code in a singleton that runs when your application starts. I'm not sure what you are using for the web application but JSF and Spring both have singleton beans for this type of use.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

java.lang.LinkageError: loader constraint violation in interface itable initialization:

From Dev

Spring java.lang.LinkageError: loader constraint violation: loader previously initiated loading for a different type with name X

From Dev

java.lang.LinkageError: loader constraint violation; when resolving interface method (in service class)

From Dev

java.lang.LinkageError: loader constraint violation When trying to use Mockito Argument Matcher

From Dev

java.lang.LinkageError: loader constraint violation:previously initiated loading for a different type with name "javax/mail/Session"

From Dev

java.lang.LinkageError: loader constraint violation When trying to use Mockito Argument Matcher

From Dev

java.lang.LinkageError: loading constraint violation

From Dev

Javassist, java

From Dev

Patching java.base results in java.lang.LinkageError

From Dev

javax.servlet.ServletException: java.lang.LinkageError

From Dev

JBoss java.lang.LinkageError when deploying EAR

From Dev

Caused by: java.lang.LinkageError: Failed to link com/---

From Dev

java.lang.LinkageError: attempted duplicate class definition

From Dev

java.lang.LinkageError: ClassCastException: in spring MVC project

From Dev

java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter

From Dev

Javassist: Convert CtMethod to java.lang.reflect.Method

From Dev

PowerMock Mockito [PowerMockito] @PrepareForTest -> java.lang.NoClassDefFoundError: javassist/NotFoundException

From Dev

PowerMock Mockito [PowerMockito] @PrepareForTest -> java.lang.NoClassDefFoundError: javassist/NotFoundException

From Dev

javassist.CannotCompileException: [source error] no such field: $1

From Dev

Java LinkageError while deploying to weblogic

From Dev

Hibernate java.lang.ClassCastException: _$$_javassist_856 cannot be cast to javassist.util.proxy.Proxy when using Websphere Shared Library

From Dev

Classloading Using Different Versions Of The Same Class : java.lang.LinkageError : attempted duplicate class definition for name

From Dev

Keep getting exception java.lang.LinkageError: Failed to link org/springframework/transaction/interceptor/TransactionInterceptor

From Dev

How to resolve a Classloader related 'java.lang.LinkageError' when sending email from Tomee?

From Dev

Elasticsearch causing java.lang.LinkageError with javax/servlet/FilterConfig on Tomcat 7

From Dev

Install4j: Windows installer showing java.lang.LinkageError: ClassCastException

From Dev

Keep getting exception java.lang.LinkageError: Failed to link org/springframework/transaction/interceptor/TransactionInterceptor

From Dev

How to resolve a Classloader related 'java.lang.LinkageError' when sending email from Tomee?

From Dev

exception when working with Java and metamodels java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot

Related Related

  1. 1

    java.lang.LinkageError: loader constraint violation in interface itable initialization:

  2. 2

    Spring java.lang.LinkageError: loader constraint violation: loader previously initiated loading for a different type with name X

  3. 3

    java.lang.LinkageError: loader constraint violation; when resolving interface method (in service class)

  4. 4

    java.lang.LinkageError: loader constraint violation When trying to use Mockito Argument Matcher

  5. 5

    java.lang.LinkageError: loader constraint violation:previously initiated loading for a different type with name "javax/mail/Session"

  6. 6

    java.lang.LinkageError: loader constraint violation When trying to use Mockito Argument Matcher

  7. 7

    java.lang.LinkageError: loading constraint violation

  8. 8

    Javassist, java

  9. 9

    Patching java.base results in java.lang.LinkageError

  10. 10

    javax.servlet.ServletException: java.lang.LinkageError

  11. 11

    JBoss java.lang.LinkageError when deploying EAR

  12. 12

    Caused by: java.lang.LinkageError: Failed to link com/---

  13. 13

    java.lang.LinkageError: attempted duplicate class definition

  14. 14

    java.lang.LinkageError: ClassCastException: in spring MVC project

  15. 15

    java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter

  16. 16

    Javassist: Convert CtMethod to java.lang.reflect.Method

  17. 17

    PowerMock Mockito [PowerMockito] @PrepareForTest -> java.lang.NoClassDefFoundError: javassist/NotFoundException

  18. 18

    PowerMock Mockito [PowerMockito] @PrepareForTest -> java.lang.NoClassDefFoundError: javassist/NotFoundException

  19. 19

    javassist.CannotCompileException: [source error] no such field: $1

  20. 20

    Java LinkageError while deploying to weblogic

  21. 21

    Hibernate java.lang.ClassCastException: _$$_javassist_856 cannot be cast to javassist.util.proxy.Proxy when using Websphere Shared Library

  22. 22

    Classloading Using Different Versions Of The Same Class : java.lang.LinkageError : attempted duplicate class definition for name

  23. 23

    Keep getting exception java.lang.LinkageError: Failed to link org/springframework/transaction/interceptor/TransactionInterceptor

  24. 24

    How to resolve a Classloader related 'java.lang.LinkageError' when sending email from Tomee?

  25. 25

    Elasticsearch causing java.lang.LinkageError with javax/servlet/FilterConfig on Tomcat 7

  26. 26

    Install4j: Windows installer showing java.lang.LinkageError: ClassCastException

  27. 27

    Keep getting exception java.lang.LinkageError: Failed to link org/springframework/transaction/interceptor/TransactionInterceptor

  28. 28

    How to resolve a Classloader related 'java.lang.LinkageError' when sending email from Tomee?

  29. 29

    exception when working with Java and metamodels java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot

HotTag

Archive