Вопрос по jar, class, reflection, java, load – Как загрузить классы во время выполнения из папки или JAR?

55

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

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

РЕДАКТИРОВАТЬ: Я думаю, что я сформулировал это плохо. Моя проблема не в том, что я не могу получить все файлы классов, я могу сделать это с помощью рекурсии и т. Д. И правильно их найти. Моя проблема заключается в получении объекта класса для каждого файла класса.

Ответы ниже позволят вам найти файлы классов, но, в зависимости от размера вашего проекта, возможно, стоит использоватькак или Javassist. Это позволит вам анализировать классы, не загружая их все в память. Nick Wilson
Как вы можете загрузить класс, игнорируя его полное имя? Я не думаю, что это возможно. Edwin Dalorzo

Ваш Ответ

3   ответа
94

о занятиях. Имена классов извлекаются из 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);

}

редактировать

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

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

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

ссылка мертва, кто-то исправит это! RayanFar
@ RayanFar: исправлено Apfelsaft
Извините, что поднял старый пост (спасибо за этот ответ, кстати, он работает для меня). Тем не мение,new URL("jar:file:" + pathToJar+"!/") вызвалаClassNotFoundException. Что сработало для меня:URL[] urls = { new URL("jar:" + pathToJar+"!/") }; Не знаешь почему? Надеюсь, это поможет кому-то еще. taylorcressy
Ницца. Вы могли бы хотеть закрыть jarFile все же? try {...} finally {jarFile.close (); } Stefan Reich
Ссылка не работает. Karl Richter
9

List Все классы внутри 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;
}
6

местоположения проекта (JAR / WAR или просто папка)

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

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

Ни то, ни другое особенно сложно. Просто прочитайте Javadoc и начните кодировать.

Похожие вопросы