【问题标题】:Custom Class Loader in java different behaviourjava中的自定义类加载器不同的行为
【发布时间】:2015-09-24 19:19:32
【问题描述】:

我正在处理一个需要从文件系统动态加载类的项目,我用谷歌搜索发现我需要使用自定义ClassLoader。我已经实现了自己的类加载器,当我在控制台上运行它时工作正常,当我尝试在服务器上部署应用程序时出现问题,它导致ClassNotFoundException

问题是我试图加载的类包含一些对另一个类的引用,该类已经由应用程序加载,但它试图从同一位置加载引用。

public class HandlerClassLoader extends ClassLoader {

static Logger log = Logger.getLogger(HandlerClassLoader.class.getName());
URLClassLoader ucl;
private ProcessDefinition processDefinition = null;
boolean flag = false;

public URL[] loadJars() throws MalformedURLException {

    PropertiesFiles propFiles = new PropertiesFiles();

    File f = new File(propFiles.getValue("jarslocation"));

    log.debug("Loading JARS files from " + f.getAbsolutePath());

    List<URL> urls = new ArrayList<URL>();

    String filesName[] = f.list();

    for (String jars : filesName)
        if (jars.endsWith("jar")) {
            urls.add(new URL("file:///"
                    + propFiles.getValue("jarslocation") + "/" + jars));
        }

    URL[] array = urls.toArray(new URL[urls.size()]);

    return array;
}

public HandlerClassLoader() {
    super(Thread.currentThread().getContextClassLoader());
    log.debug("Called to the " + this.getClass().getName()
            + " No Parameter Constructor");
    try {
        ucl = new URLClassLoader(loadJars());

    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

public HandlerClassLoader(ClassLoader parent,
        ProcessDefinition processDefinition) {
    super(parent);
    log.debug("Called to the " + this.getClass().getName()
            + " Parameterized Constructor");
    try {
        ucl = new URLClassLoader(loadJars());
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
    this.processDefinition = processDefinition;
}

public Class<?> findClass(String className) throws ClassNotFoundException {
    log.debug("findClass method of " + this.getClass().getName()
            + " is called with className : " + className);

    return ucl.loadClass(className);
}

我认为委托原则不起作用,或者该服务器可能必须具有不同的类加载器实现。

【问题讨论】:

  • 你真的实现了自己的类加载器吗?很可能你可以使用URLClassLoader 来加载你的类,它会正确地委托给父类。
  • @Kayaman 是的,我使用 URLClassLoader 实现了自己的类加载器,并且在构造函数中传递了父类加载器
  • @Kayaman 我已经提供了我的类加载器
  • 您的 ClassLoader 实现并没有真正添加任何有用的东西。为什么不直接使用URLClassLoader

标签: java classloader


【解决方案1】:

很可能,您没有委托给正确的父母。我假设选择Thread.currentThread().getContextClassLoader() 会导致在应用服务器上使用错误的类加载器,而这只是从控制台应用程序运行时的系统类加载器(类路径)。

因此,您需要确保您交给自定义类加载器的父级能够看到您打算通过它加载的类。

最后一点,实现自己的类加载器是一件棘手的事情。例如,您没有考虑定位资源或定义包。您正在使用的第三方库可能需要这两者。如果您真的只需要从磁盘加载文件,请考虑使用URLClassLoader

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多