简体   繁体   English

Java中的自定义类加载器的不同行为

[英]Custom Class Loader in java different behaviour

I am working on a project which requires dynamic Loading of a class from a file system, I googled and found out that I need to use custom ClassLoader . 我正在研究一个需要从文件系统动态加载类的项目,我用Google搜索了一下,发现我需要使用自定义ClassLoader I have implemented my own class loader which is working fine when I run it on console, the problem I when I try to deploy the application on the server it results in ClassNotFoundException . 我已经实现了我自己的类加载器,当我在控制台上运行该类加载器时,它可以正常工作,当我尝试在服务器上部署应用程序时,该问题导致ClassNotFoundException

The problem is the class which I am trying to load contain some references to another class which is already loaded by the application but it is trying to load the reference from the same location. 问题是我试图加载的类包含对另一个已经由应用程序加载的类的引用,但是它试图从同一位置加载引用。

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

I think the delegation principle is not working or maybe that server must have a different implementation of classloader. 我认为委托原则不起作用,或者服务器必须具有不同的类加载器实现。

Most likely, you do not delegate to the correct parent. 您很可能没有委派给正确的父母。 I assume that picking up Thread.currentThread().getContextClassLoader() results in using the wrong class loader on the application server while this is simply the system class loader (class path) when running from a console app. 我假设选择Thread.currentThread().getContextClassLoader()导致在应用程序服务器上使用错误的类加载器,而这只是从控制台应用程序运行时的系统类加载器(类路径)。

Therefore, you need to make sure that the parent that you are handing to your custom class loader is capable of seeing the classes you are intending to load by it. 因此,您需要确保交给您的自定义类加载器的父类能够查看您打算由其加载的类。

On a final note, implementing your own class loader is a tricky business. 最后一点,实现自己的类加载器是一件棘手的事情。 For example, you have not accounted for locating ressources or for defining packages. 例如,您没有考虑定位资源或定义程序包。 Both might be required by third-party libraries that you are using. 您正在使用的第三方库可能都需要这两个。 If you really only need to load files from disk, consider using a URLClassLoader . 如果确实只需要从磁盘加载文件,请考虑使用URLClassLoader

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM