Ramesh Ramesh - 3 months ago 8
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.