我正在尝试从jar文件加载类。基本上,我想在该jar的包中调用特定类中的方法。我在这里遇到的问题是,从jar成功加载类后,当我尝试实例化时,我得到异常:ClassNotFound用于在我的类中导入的类。
这是加载类的类:
输入:D:\ Myjar.jar,com.vendor.epbroker.VNFLCMCommunicator
public Class<?> loadClass(String libPath, String pkgName) {
LogManager.getLogger().info("Adding Class");
File jarFile = null;
try {
jarFile = new File(libPath);
URL fileURL = jarFile.toURI().toURL();
String jarURL = "jar:" + fileURL + "!/";
URL urls[] = { new URL(jarURL) };
URLClassLoader ucl = new URLClassLoader(urls);
Class<?> beanClass = ucl.loadClass(pkgName);
ucl.close();
return beanClass;
} catch (Exception ex) {
LogManager.getLogger().error("Given Library: " + libPath + " or Class name: " + pkgName + " is not Valid");
LogManager.getLogger().error("Exception occurred : ", ex);
}
LogManager.getLogger().error("Class loading Error: Returning NULL");
return null;
}
接收此类的代码段:
Object instance = classToLoad.newInstance();
// To get the list of methods exist in the Class
Method[] listOfMethods = classToLoad.getMethods();
遇到以下错误:
SEVERE: Servlet.service() for servlet [spring] in context with path [/vnflcm] threw exception [Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/vendor/epbroker/exception/EPBrokerException] with root cause
java.lang.ClassNotFoundException: com.vendor.epbroker.exception.EPBrokerException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructor0(Class.java:3075)
任何帮助都会受到赞赏吗?
答案 0 :(得分:0)
尝试使用Reflection
时,您需要考虑一些因素。
正如@VGR指出的那样,你不能简单地使用jar的文件路径作为URL。你可以做的一件事是:
File myJar = new File("path/to/myJar.jar");
URL myJarUrl = myJar.toURI().toURL();
一个证明问题的简单示例:
让我们调用你的jar myToolProject。让我们说开发这个工具时你创建了一个类,称之为JsonMaker
,它将POJO转换为JSON,然后通过gson.jar
完成。当你构建你的jar时,我们称之为myjar.jar,你在清单中提到它依赖于gson。
当试图反思myjar时,你会反思你的jar中的每个类,直到你到达JsonMaker.class
。在尝试反映此处时,我们注意到此处存在com.google.Gson
类型对象。 URLClassLoader查看其数组中的URLS并尝试在某个类中查找com.google.Gson
。如果找不到任何com.google.Gson
类,则无法反映该类,并抛出ClassNotFoundException
。
答案 1 :(得分:0)
看看以下几行:
URLClassLoader ucl = new URLClassLoader(urls);
Class<?> beanClass = ucl.loadClass(pkgName);
ucl.close();
并考虑URLClassLoader.close()
的文档:
关闭此URLClassLoader,以便它不再可用于加载此加载程序定义的新类或资源。
换句话说,如果你真的使用了那个加载器的类,你应该只关闭一个类加载器。即使此时已经加载了所有必需的类,仍然可能需要访问所需的资源。请注意,某些框架有自己的反射库,需要访问类的字节代码,这些代码将像资源一样进行访问。
在您的具体情况下,它甚至更简单。您刚刚加载了一个类,它只触发了所需的最小类集(例如直接超类)的解析,但没有其他依赖项。然后关闭类加载器,防止后续加载jar文件中的任何其他类,当解析构造函数需要解析更多引用的类时,这会打击你。