custom classLoader issue

2019-03-02 18:57发布

问题:

the problem is next: i took the base classLoader code from here. but my classLoader is specific from a point, that it must be able to load classes from a filesystem(let's take WinOS), so in classLoader must be some setAdditionalPath() method, which sets a path(a directory on a filesystem), from which we'll load class(only *.class, no jars). here is code, which modifies the loader from a link(you can see, that only loadClass is modified), but it doesn't work properly:

public void setAdditionalPath(String dir) {
            if(dir == null) {
                throw new NullPointerException("");
            }

            this.Path = dir;
        }

        public Loader(){
              super(Loader.class.getClassLoader());
        }


        public Class loadClass(String className) throws ClassNotFoundException {
          if(Path.length() != 0) {
            File file = new File(Path);

            try {
                // Convert File to an URL

         URL url = file.toURL();          
                URL[] urls = new URL[]{url};

                // Create a new class loader with the directory
                ClassLoader cl = new URLClassLoader(urls);


                ClassLoader c = cl.getSystemClassLoader();
                Class cls = c.loadClass(className);
                return cls;

            } catch (MalformedURLException e) {

            } catch (ClassNotFoundException e) {

            }

        }
            return findClass(Path);
        }

I'd grateful if anyone helps :)

回答1:

You can just use framework provided java.net.URLClassLoader. No need to write your own. It supports loading of classes from directories and JAR files.

Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed.

It also supports a parent class loader. If this class loader does not suite your requirements, perhaps you can specify in more detail what you need. And in any case, you can look at the source and derive your own class loader class based on that.

Here is a short working snippet of code that should demostrate how to load a class by name from a URLClassLoader:

    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

    // This URL for a directory will be searched *recursively*
    URL classes =
        new URL( "file:///D:/code/myCustomClassesAreUnderThisFolder/" );

    ClassLoader custom = 
        new URLClassLoader( new URL[] { classes }, systemClassLoader );

    // this class should be loaded from your directory
    Class< ? > clazz = custom.loadClass( "my.custom.class.Name" ); 
    // this class will be loaded as well, because you specified the system 
    // class loader as the parent
    Class< ? > clazzString = custom.loadClass( "java.lang.String" );