How to load Classes at runtime from a folder or JAR?

回眸只為那壹抹淺笑 提交于 2019-12-16 22:21:26

问题


I am trying to make a Java tool that will scan the structure of a Java application and provide some meaningful information. To do this, I need to be able to scan all of the .class files from the project location (JAR/WAR or just a folder) and use reflection to read about their methods. This is proving to be near impossible.

I can find a lot of solutions based on URLClassloader that allow me to load specific classes from a directory/archive, but none that will allow me to load classes without having any information about the class name or package structure.

EDIT: I think I phrased this poorly. My issue is not that I can't get all of the class files, I can do that with recursion etc. and locate them properly. My issue is obtaining a Class object for each class file.


回答1:


The following code loads all classes from a JAR file. It does not need to know anything about the classes. The names of the classes are extracted from the JarEntry.

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

URL[] urls = { new URL("jar:file:" + pathToJar+"!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);

while (e.hasMoreElements()) {
    JarEntry je = e.nextElement();
    if(je.isDirectory() || !je.getName().endsWith(".class")){
        continue;
    }
    // -6 because of .class
    String className = je.getName().substring(0,je.getName().length()-6);
    className = className.replace('/', '.');
    Class c = cl.loadClass(className);

}

edit:

As suggested in the comments above, javassist would also be a possibility. Initialize a ClassPool somewhere before the while loop form the code above, and instead of loading the class with the class loader, you could create a CtClass object:

ClassPool cp = ClassPool.getDefault();
...
CtClass ctClass = cp.get(className);

From the ctClass, you can get all methods, fields, nested classes, .... Take a look at the javassist api: https://jboss-javassist.github.io/javassist/html/index.html




回答2:


List All the classes inside jar file.

public static List getClasseNames(String jarName) {
    ArrayList classes = new ArrayList();

    if (debug)
        System.out.println("Jar " + jarName );
    try {
        JarInputStream jarFile = new JarInputStream(new FileInputStream(
                jarName));
        JarEntry jarEntry;

        while (true) {
            jarEntry = jarFile.getNextJarEntry();
            if (jarEntry == null) {
                break;
            }
            if (jarEntry.getName().endsWith(".class")) {
                if (debug)
                    System.out.println("Found "
                            + jarEntry.getName().replaceAll("/", "\\."));
                classes.add(jarEntry.getName().replaceAll("/", "\\."));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return classes;
}



回答3:


To do this, I need to be able to scan all of the .class files from the project location (JAR/WAR or just a folder)

Scanning all of the files in a folder is simple. One option is to call File.listFiles() on the File that denotes the folder, then iterate the resulting array. To traverse trees of nested folders, use recursion.

Scanning the files of a JAR file can be done using the JarFile API ... and you don't need to recurse to traverse nested "folders".

Neither of these is particularly complicated. Just read the javadoc and start coding.



来源:https://stackoverflow.com/questions/11016092/how-to-load-classes-at-runtime-from-a-folder-or-jar

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