Question

The code is as follows

what it does is it loads all the classes inside a jar file which I placed inside my home directory .

import java.io.File;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;
import java.net.URLClassLoader;
import java.net.URL;
import java.util.Enumeration;
import java.lang.ClassLoader;
public class Plugin extends ClassLoader {
public static void main(String[] args) throws Exception {

    File file = new File(System.getProperty("user.home") + "/HelloWorld.jar");

    URLClassLoader clazzLoader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()});

    JarFile jarFile = new JarFile(file);
    Enumeration<JarEntry> entries = jarFile.entries();

    while (entries.hasMoreElements()) {
        JarEntry element = entries.nextElement();
        if (element.getName().endsWith(".class")) {
            try {
                Class c = clazzLoader.loadClass(element.getName().replaceAll(".class", "").replaceAll("/", "."));
                c.newInstance(); // this proves that class is loaded
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    Class cls = Class.forName("HelloWorld");
    cls.newInstance();
    Plugin p = new Plugin();
    p.checkIfLoaded();

}

public void checkIfLoaded() {
System.out.println("coming in");
if (findLoadedClass("HelloWorld") != null){
        System.out.println("Yepee, HelloWorld class is loaded !");
}
}

}

My HelloWorld is as in https://github.com/HarishAtGitHub/doc/blob/master/makeExecutableJar/HelloWorld.java

and the jar is got using the instructions in my github account mentioned above .

c.newInstance() works .

How did I confirm ?

the static block got executed ...

but Class.forName("HelloWorld") throws ClassNotFoundException

also findLoadedClass("HelloWorld") is null ..

I cannot understand why this strange behaviour ?

Please guide ...

Was it helpful?

Solution

This is a classloader issue.

As per the Javadocs to Class.forName, you are looking up the class using the classloader of the current class. As your main class, this will be the JVM's bootstrap classloader (and will more or less just include the standard library plus anything you provided as a -cp command line argument). It is not going to delegate to the classloader that you instantiated as a local variable, and so will not return classes that that classloader could find.

If you were to specify the classloader explicitly, and call

Class.forName("HelloWorld", true, clazzloader)

then the classloader you just created will be searched instead and your class should be found.

OTHER TIPS

Because Class.forName(String) uses currentClassLoader and you have load the class in different ClassLoader.

According with javadoc, invoking Class.forName(String) is equivalent to:

Class.forName(className, true, currentLoader) 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top