Ramesh Ramesh - 9 months ago 33
Java Question

NoSuchMethodException exception when class is loaded via URLClassLoader

This question is slightly different from the previous error reported via Unable to invoke method by java reflection: NoSuchMethodException



Signature of overloading methods follow as below in target class, my objective is to invoke

public List run(FileInput,StreamOutput)
dynamically.

public List run(String, String);
public List run(FileInput,StreamOutput);


Case 1: When dynamically loading a method using reflection api when target class(jar) is present in CLASS_PATH - method is accessible.

Class mapClass = loader.loadClass("com.sample.test.TrackingService");
FileInput input = new FileInput(inputFileFullPath);
StreamOutput output = new StreamOutput(new java.io.ByteArrayOutputStream());

Object mapObj = mapClass.newInstance();
Class params[]={ FileInput.class,StreamOutput.class};
Method m = mapClass.getDeclaredMethod("run", params);

outputList = (List) m.invoke(mapObj, input,output);`


Case 2: On top of the same code in Case 1, instead of placing jar in CLASS_PATH, but loaded via
URLClassLoader
then it throws
NoSuchMethodException


Code block

URL urls[] = {new URL("file:/opt/jars/Tracking.jar")};
URLClassLoader loader = new URLClassLoader(urls);
Class mapClass = loader.loadClass("com.sample.test.TrackingService",true,loader);
FileInput input = new FileInput(inputFileFullPath);
StreamOutput output = new StreamOutput(new java.io.ByteArrayOutputStream());
Object mapObj = mapClass.newInstance();
Class params[]={ FileInput.class,StreamOutput.class};
Method m = mapClass.getDeclaredMethod("run", params);

outputList = (List) m.invoke(mapObj, input,output);


Exception is thrown at line
Method m = mapClass.getDeclaredMethod("run", params);


Question 1: Is something missing here when loading class via URLClassLoader ?

Question 2: Any recommendation on loading class definition into JVM via custom class. I mean, achieving same level as jar file present in CLASS_PATH ? Part of our requirement and limitation we can't place jar under CLASS_PATH or add jar path to CLASS_PATH

Answer

It worked when the class loader changed as shown below.

URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:/opt/jars/Tracking.jar") }, this.getClass().getClassLoader());

Rest everything same... as I said, with-out adding the current class loader also worked when run in eclipse.