通过URLClassLoader加载类时的NoSuchMethodException异常

时间:2016-08-17 04:01:00

标签: java reflection classpath invoke

此问题与之前通过Unable to invoke method by java reflection: NoSuchMethodException

报告的错误略有不同


重载方法的签名遵循如下目标类,我的目标是动态调用public List run(FileInput,StreamOutput)

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

案例1:当CLASS_PATH中存在目标类(jar)时,使用反射api动态加载方法时,方法可以访问

    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);`

案例2:在案例1中的相同代码之上,而不是将jar放在CLASS_PATH中,而是通过URLClassLoader加载,然后它会抛出NoSuchMethodException

代码块

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);

在行Method m = mapClass.getDeclaredMethod("run", params);

处抛出异常

问题1:通过URLClassLoader加载课程时是否缺少某些内容?
问题2:有关通过自定义类将类定义加载到JVM的任何建议。我的意思是,达到与CLASS_PATH中存在的jar文件相同的级别?我们的要求和限制的一部分,我们不能将jar放在CLASS_PATH下或将jar路径添加到CLASS_PATH

2 个答案:

答案 0 :(得分:0)

两个代码之间应该改变的一切(一个使用ClassLoader,另一个使用URLClassLoader)是实例化,即

此:

ClassLoader loader = getClass().getClassLoader();
Class<?> myLib = loader.loadClass("com.chetan.loader.MyLib");  

应替换为:

URL url[] = {new URL("file:C:\\Chetan\\mylib-0.0.1-SNAPSHOT.jar")};
URLClassLoader loader = new URLClassLoader(url);
Class<?> myLib = loader.loadClass("com.chetan.loader.MyLib");   

这是我推荐的内容,虽然你可能已经尝试过这些东西,但是如果你没有:

  1. 解压缩Jar /opt/jars/Tracking.jar(您可以通过Winzip或其他类似工具打开它),然后反编译类TrackingService - 检查它是否包含您尝试调用的方法

  2. 为您提供新的代码/模拟 - 我建议使用两种方法变体创建一个小类。把它装在一个罐子里。创建一个测试加载器类并尝试使用URLClassLoader - 这将使您确信您编写的代码有效。然后,您可以查找问题的其他方面。

  3. 无论如何,如果以上建议有效,请告诉我。如果您无法使测试类正常工作,请共享代码,以便此处的成员可以更好地了解您要执行的操作。

答案 1 :(得分:0)

当类加载器改变时,如下所示。

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

休息一切......就像我说的那样,没有添加当前的类加载器也可以在eclipse中运行时工作。