在Java中使用反射加载已加载类的导入类

在Java中使用反射加载已加载类的导入类,java,exception,reflection,Java,Exception,Reflection,我试图从jar文件加载类。基本上,我想在jar的包中调用特定类中的方法。我在这里面临的问题是,在成功地从jar加载类之后,当我尝试实例化时,对于在我的类中导入的类,我得到了exception:ClassNotFound 下面是加载该类的类: 输入:D:\Myjar.jar,com.vendor.epbroker.vnflcmccommunicator public Class<?> loadClass(String libPath, String pkgName) {

我试图从jar文件加载类。基本上,我想在jar的包中调用特定类中的方法。我在这里面临的问题是,在成功地从jar加载类之后,当我尝试实例化时,对于在我的类中导入的类,我得到了exception:ClassNotFound

下面是加载该类的类:

输入:D:\Myjar.jar,com.vendor.epbroker.vnflcmccommunicator

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;
    }
遇到以下错误:

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)

如果您有任何帮助,我们将不胜感激。

在尝试使用
反射时,您必须考虑以下几点

  • URLClassLoader必须包含要反映到的jar的URL
  • 如果所需的jar依赖于任何其他jar,则必须同时加载这些jar的url
  • 正如@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
    type对象。URLClassLoader查看其数组中的URL,并尝试在某个类中查找
    com.google.Gson
    。如果它找不到任何
    com.google.Gson
    类,它将无法反映该类,并抛出一个
    ClassNotFoundException

    查看以下行:

    URLClassLoader ucl = new URLClassLoader(urls);
    Class<?> beanClass = ucl.loadClass(pkgName);
    ucl.close();
    
    URLClassLoader ucl=新的URLClassLoader(URL);
    类beanClass=ucl.loadClass(pkgName);
    ucl.close();
    

    并考虑文献:

    关闭此URLClassLoader,使其不再用于加载此装入器定义的新类或资源

    换句话说,只有当您真正使用了类加载器的类时,才应该关闭该类加载器。即使此时已经加载了所有必需的类,仍然有可能需要访问必需的资源。注意,有些框架有自己的反射库,需要访问类的字节码,这些字节码将像资源一样被访问


    在您的特定情况下,它甚至更简单。您刚刚加载了一个类,它只触发了所需的最小类集的解析(例如direct super类),但没有其他依赖项。然后关闭类加载器,防止后续从jar文件加载任何其他类,当解析构造函数需要解析更多引用的类时,会遇到这种情况。

    删除
    字符串jarURL=…
    行。URL根本不应该是“jar:”URL。只要做
    URL[]={fileURL}@VGR这也没有帮助。执行此操作仍然会产生相同的错误。此外,com.google.gson.gson和其他软件包中的类也出现了错误。不确定如何解决此问题。您说错误发生在您尝试加载com.google.gson.gson时,但异常表示找不到com.vendor.epbroker.exception.EPBrokerException。EPBrokerException.class是否在.jar文件中?
    
    URLClassLoader ucl = new URLClassLoader(urls);
    Class<?> beanClass = ucl.loadClass(pkgName);
    ucl.close();