Подтвердить что ты не робот

Как загружать классы во время выполнения из папки или JAR?

Я пытаюсь создать инструмент Java, который сканирует структуру приложения Java и предоставит некоторую значимую информацию. Для этого мне нужно иметь возможность сканировать все файлы .class из местоположения проекта (JAR/WAR или только папку) и использовать рефлексию для чтения своих методов. Это оказывается почти невозможным.

Я могу найти множество решений на основе URLClassloader, которые позволяют загружать определенные классы из каталога/архива, но ни один из них не позволит мне загружать классы без какой-либо информации о имени класса или структуре пакета.

EDIT: Я думаю, что я сформулировал это плохо. Моя проблема не в том, что я не могу получить все файлы классов, я могу сделать это с рекурсией и т.д. И найти их правильно. Моя проблема - получить объект Class для каждого файла класса.

4b9b3361

Ответ 1

Следующий код загружает все классы из JAR файла. Ему не нужно ничего знать о классах. Имена классов извлекаются из 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);

}

изменить:

Как было предложено в комментариях выше, джавассист также будет возможностью. Инициализируйте ClassPool где-то до цикла while, сформировав код выше, и вместо загрузки класса с загрузчиком класса вы можете создать объект CtClass:

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

Из ctClass вы можете получить все методы, поля, вложенные классы,.... Взгляните на javassist api: https://jboss-javassist.github.io/javassist/html/index.html

Ответ 2

Список всех классов внутри файла jar.

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

Для этого мне нужно иметь возможность сканировать все файлы .class из местоположения проекта (JAR/WAR или только папка)

Сканирование всех файлов в папке прост. Один из вариантов заключается в вызове File.listFiles() в File, который обозначает папку, а затем итерации результирующего массива. Чтобы перемещаться по деревьям вложенных папок, используйте рекурсию.

Сканирование файлов JAR файла можно выполнить с помощью API JarFile... и вам не нужно рекурсивно проходить через вложенные "папки".

Ни один из них не является особенно сложным. Просто прочитайте javadoc и начните кодирование.