Search code examples
javastringfile-handlingurlclassloader

Java URLClassLoader not recognising a String


I've got a really strange problem.

I'm using a URLClassLoader to dynamically import files from a directory. The code works fine if I use a literal string, and works fine if I use a variable to a literal string, but this isn't what I need.

package test;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class Test {
    public static void main(String[] args) {

        try {
            File subfolder = new File("C:\\temp\\");
            URL classUrl = subfolder.toURI().toURL();
            URL[] classUrls = { classUrl };
            URLClassLoader ucl = new URLClassLoader(classUrls);

            for (File f : subfolder.listFiles()) {

                String name = f.getName()
                        .substring(0, f.getName().lastIndexOf(".")).trim();
                if (name.equals("TestClass"))
                        System.out.println(name);
                try {
                    MyInterface de = (MyInterface) Class.forName("TestClass", true, ucl)
                            .newInstance();
                    de.printSomething();
                } catch (ClassNotFoundException e) {
                }

                ucl.close();

            }
        } catch (MalformedURLException e) {
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

What I need is to be able to do this:

MyInterface de = (MyInterface) Class.forName(name, true, ucl).newInstance();

But it's not working even though "name" is a valid String and does equal "TestClass".

EDIT: I get the error:

java.lang.ClassNotFoundException: TestClass
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at test.Test.main(Test.java:25)

What's wrong?


Solution

  • I guess this is because of the ucl.close() inside the for loop. I added some test if there are directories: the following class works and instanciate itself if declared in the root package, and if eclipse is configure to generate .class file in "bin" directory:

    public class Toto {
    
        public Toto(){
            // this writes "Toto" in the console if the class is well instanciated
            System.out.println("Toto");
        }
    
        public static void main(String[] args) {
            try {
                File subfolder = new File("bin");
                URL classUrl = subfolder.toURI().toURL();
                URL[] classUrls = { classUrl };
                URLClassLoader ucl = new URLClassLoader(classUrls);
    
                for (File f : subfolder.listFiles()) {
                    String fileName= f.getName();
                    int suffix = fileName.lastIndexOf('.');
                    if(f.isDirectory() || suffix==-1){
                        continue;
                    }
                    String name = fileName.substring(0, suffix);
                    try {
                        Class.forName(name, true, ucl).newInstance();
    
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                ucl.close();
            } catch (MalformedURLException e) {
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }