Lasirana
Lasirana

Reputation: 51

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

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?

Upvotes: 3

Views: 12929

Answers (2)

Nicolas Filotto
Nicolas Filotto

Reputation: 44965

The method Class.forName(String) uses the ClassLoader of the caller class, if you want to use a specific ClassLoader to load your class you need to use Class.forName(String name, boolean initialize, ClassLoader loader) instead as next:

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

NB: This will work if and only if the URL that you provide to your DynamicURLClassLoader is valid and is the path to the parent folder in which you have your class

Upvotes: 2

Stephen C
Stephen C

Reputation: 718768

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:

Upvotes: 3

Related Questions