Элегантный способ сравнить содержимое JAR (для поиска новых классов и методов)

#java #jar #classloader

#java #jar #classloader

Вопрос:

Да, в Интернете написано — «распакуйте их все, декомпилируйте и сравните код с помощью какого-нибудь инструмента (total comander, WinCompare, meld (Linux), чего угодно …) Причина, по которой мне нужен инструмент для автоматической генерации отчета о различиях из Fodler1 и Folder2, проста — в этих папках слишком много JAR, и мне нужно сравнивать эти папки (со следующей версией Jar), скажем, 1 раз в месяц. Итак, я действительно совсем не хочу делать это вручную!

Давайте посмотрим, что у меня получилось на данный момент:

1) Я могу найти все JAR в каждой папке 🙂

2) Я могу получить список классов из каждого JAR:

 private static void AddAllClassesFromJAR(JarInputStream jarFile,
        ArrayList<String> classes) throws IOException {
    JarEntry jarEntry = null;
    while (true) {
        jarEntry = jarFile.getNextJarEntry();
        if (jarEntry == null) {
            break;
        }
        if (jarEntry.getName().endsWith(".class")) {
            classes.add(jarEntry.getName());
        }
    }
}

    public static List<String> getClasseNamesInPackage(String jarName) {
    ArrayList<String> classes = new ArrayList<String>();
    try {
        JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
        AddAllClassesFromJAR(jarFile, classes);
    } catch (Exception e) {
        e.printStackTrace();
    }
        return classes;
    }
  

3) В Java есть отражение (Core Java 2, том I — Основы, пример 5-5), поэтому я могу получить список методов из одного класса, как только узнаю его название.

Для этого мне нужно создать экземпляр каждого класса, проблема в том, как я могу создать экземпляр каждого класса, который я получил из каждого файла JAR? Теперь я загружаю каждый JAR:

 loader_left = new JarClassLoader("left/1.jar");

public class JarClassLoader extends URLClassLoader {
  public JarClassLoader( URL url ) {
    super( new URL[]{url} );
  }

  public JarClassLoader( String urlString ) throws MalformedURLException {
    this( new URL( "jar:file://"   urlString   "!/" ) );
  }
  

Никаких исключений, но я не могу найти в нем ни одного ресурса, пытаясь загрузить класс, подобный:

 class_left = loader_left.loadClass("level1.level2.class1");
  

И получаем «java.lang.ClassNotFoundException».

Есть какие-нибудь ссылки, в чем проблема? (имя класса проверено. он жестко запрограммирован только для тестирования, в идеале он должен получать его из списка классов)

Второй вопрос: поскольку большинство классов в Folder1 и Folder2 будут одинаковыми, что произойдет, если я загружу тот же класс во второй раз (из Fodler2)?

Комментарии:

1. Просто интересно из любопытства, зачем вам это нужно делать.

Ответ №1:

Попробуйте утилиту jarcomp.

Ответ №2:

Это не дает прямого ответа на ваш вопрос, однако вы можете ознакомиться с фреймворком ASM . Это позволяет анализировать байт-код без необходимости загружать классы с помощью загрузчика классов. Вероятно, проще сделать это таким образом.

Комментарии:

1. Спасибо, Данило, ты дал мне правильное направление — «анализировать байт-код файлов классов»… Я нашел библиотеку BCEL ( jakarta.apache.org/bcel ).