Though my class was loaded, Class.forName throws ClassNotFoundException

柔情痞子 提交于 2019-12-11 02:54:45

问题


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 ...


回答1:


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.




回答2:


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) 


来源:https://stackoverflow.com/questions/21749741/though-my-class-was-loaded-class-forname-throws-classnotfoundexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!