Sergey Solomevich Sergey Solomevich - 1 year ago 247
Java Question

Javassist, java

I'm doing a task to create a java-application. The task is to change the method (calculation formula) without recompiling the application. After searching in Google, I realized that you can solve the problem with the help of javassist. So far I'm trying on a simple example.
So, the class containing the only method I want to change

package ru.testScandJavaCafee.service;
public class Helper {
public String createList()
{
System.out.println("++++");
return "1000";
}
}


And the class from which I change the method

package ru.testScandJavaCafee.controller;

import javassist.*;
import ru.testScandJavaCafee.service.Helper;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


/**
* Created by 15 on 06.05.2017.
*/

public class CoffeeTypeController {

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

ClassPool pool = ClassPool.getDefault();
ClassPool.getDefault().insertClassPath(new ClassClassPath(ru.testScandJavaCafee.service.Helper2.class));

CtClass cc = pool.get("ru.testScandJavaCafee.service.Helper");

CtMethod cm = cc.getMethod("createList","()Ljava/lang/String;" );

cm.setBody( "{ return \"200 \" ;}" );
cc.toClass();

Helper helper = new Helper();
Method method1 = helper.getClass().getMethod("createList");
String sum = (String)method1.invoke(helper);
return sum;
}


After starting I get the output

javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of org/apache/catalina/loader/WebappClassLoader): attempted duplicate class definition for name: "ru/testScandJavaCafee/service/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:111)
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/service/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

Answer Source

You error is in this line:

ClassPool.getDefault().insertClassPath(new ClassClassPath(ru.testScandJavaCafee.service.Helper2.class));

First, you already created the pool so should insert the classpath to that pool. Second, the class path is supposed to be the class name of the class where your code resides.

pool.insertClassPath(new ClassClassPath(this.getClass()));

Check out the documentation. The section on Class search path

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download