Can't find Class with Class.forName() but it exists

Lasirana picture Lasirana · Sep 22, 2016 · Viewed 8.6k times · Source

I have a program in which I am generating classes at runtime (included only variable and associated getters and setters methods). Later I want to fill the classes.

To get the class - I know its Name, but its not in the classpath - I tried .forName() but I always get a ClassNotFoundException.

Here is my example:

Exception in thread "main" java.lang.ClassNotFoundException: com.test.wam.business.wsobjects.Testclass
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at gui.Application.main(Application.java:94)

And the code:

URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    DynamicURLClassLoader dynamicURLClassLoader = new DynamicURLClassLoader(urlClassLoader);
    dynamicURLClassLoader.addURL(new URL("file://C:\\dev\\Eclipse_was\\guitest\\generated"));

    Class c = Class.forName("com.test.wam.business.wsobjects.Testclass");

    Object classInstance = c.newInstance();

The ClassLoader:

public class DynamicURLClassLoader extends URLClassLoader {

public DynamicURLClassLoader(URLClassLoader classLoader) {
    super(classLoader.getURLs());
}

@Override
public void addURL(URL url) {
    super.addURL(url);
}

}

The full qualified Name to the file (created with eclipse -> copy full qualified Name)

/guitest/generated/com/test/wam/business/wsobjects/Testclass.java

What is wrong here?

Answer

Stephen C picture Stephen C · Sep 22, 2016

I can see two problems:

1) You are creating a DynamicURLClassLoader and adding the URL to it, but you are not actually using it. This statement:

 Class c = Class.forName("com.test.wam.business.wsobjects.Testclass");

will use the classloader that loaded the current class. That is probably the application's default classloader, but it is certainly NOT the classloader you just created. The javadoc says:

[Class.forName(className)] returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:

Class.forName(className, true, currentLoader) 

where currentLoader denotes the defining class loader of the current class.

So .... the solution is:

Class c = Class.forName("com.test.wam.business.wsobjects.Testclass",
                        true, dynamicURLClassLoader);

2) This string:

"file://C:\\dev\\Eclipse_was\\guitest\\generated"

is not a valid "file:" URL. The correct URL for the path you are trying to reference would be:

"file:///C:/dev/Eclipse_was/guitest/generated"

The way that you wrote the URL might work, but it is not the correct way to do it.

Reference: