Reputation: 1272
i am trying to create a dynamic class and its object and trying to call method of method of class dynamic using object but i am getting following error
java.lang.ClassNotFoundException: Eval
here is my code please suggest any changes to make it run successfully
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtNewMethod;
public class DyanamicClass {
/**
* @param args
*/
public static void main (String[] args) throws Exception {
createClass();
Object obj=createObject();
Object[] actualParams = new Object[] { new Double(17) };
callMethod("eval", obj,actualParams);
}
public static void createClass()
{
ClassPool pool = ClassPool.getDefault();
CtClass evalClass = pool.makeClass("Eval");
try {
evalClass.addMethod(
CtNewMethod.make("public double eval (double x) { return x ; }", evalClass));
} catch (CannotCompileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Object createObject()
{
Object obj=null;
try {
Class clazz = Class.forName("Eval");
obj=clazz.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
public static void callMethod(String name,Object obj,Object [] actualParams)
{
Class[] formalParams = new Class[] { double.class };
double result;
try {
Class clazz=Class.forName("Eval");
Method meth = clazz.getDeclaredMethod(name, formalParams);
result = ((Double) meth.invoke(obj, actualParams)).doubleValue();
System.out.println(result);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Upvotes: 0
Views: 2094
Reputation: 3533
I have tested some things in the implementation of the Javassist. Understand that i dont understand this library, but my assumption is that the ClassLoader used by the Class.forName() (Probably the current Thread context class loader - need to check that) cannot find the class file for Eval because it is does not have information on its classpath. I am very sure the javassist has ClassPath information you need to set for the class in order for the normal ClassLoaders be able to find its class file information. Moreover, you probably need to save the class file to file provided by the javassist.
However, as a work around, do the following (Note, that javassist says that after calling toClass() on CtClass, it cannot be used again).
CtClass ct =ClassPool.getDefault().getCtClass("Eval");
System.out.println(ct);
Class cl = ct.toClass();
Object o = cl.newInstance();
Method m = cl.getDeclaredMethod("eval", new Class[]{double.class});
Object res = m.invoke(o, 56);
System.out.println(res);
System.out.println(cl);
System.out.println(Arrays.toString(cl.getDeclaredMethods()));
Upvotes: 1
Reputation: 785146
You are trying to load your class here:
Class clazz = Class.forName("Eval");
Eval
is available in your classpath.Eval
you have to give packageName.className
so something like org.test.Eval
.Upvotes: 0