通过 URLClassLoader 加载 class 时出现 NoSuchMethodException 异常

NoSuchMethodException exception when class is loaded via URLClassLoader

这个问题与之前通过

报告的错误略有不同


重载方法的签名如下在目标 class 中,我的 objective 是动态调用 public List run(FileInput,StreamOutput)

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

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

    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 加载 class 时是否缺少某些内容?
问题 2:关于通过自定义 class 将 class 定义加载到 JVM 的任何建议。我的意思是,达到与 CLASS_PATH 中存在的 jar 文件相同的水平?我们的部分要求和限制是我们不能将 jar 放在 CLASS_PATH 下或将 jar 路径添加到 CLASS_PATH

两个代码(一个使用 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 或其他类似的实用程序打开它),然后反编译 class TrackingService - 检查是否可以包含您要调用的方法?

  2. 让您的代码焕然一新/模拟 - 我建议使用两种方法变体创建一个小的 class。把它装在一个罐子里。创建一个测试加载器 class 并尝试使用 URLClassLoader - 这会让您相信您编写的代码可以正常工作。然后您可以查找问题的其他方面。

无论如何,如果以上建议有效,请告诉我。如果您无法使测试 class 正常工作,请分享代码,以便这里的其他成员可以更好地理解您正在尝试做什么。

它在 class 加载程序更改时起作用,如下所示。

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

其他一切都一样...正如我所说,不添加当前 class 加载程序在 运行 在 eclipse 中时也能正常工作。