Search code examples
javajarclassloader

Elegant way to compare the content of JARs (to find new classes and methods)


Yes, the Internet says - "unzip them all, decompile and compare the code with some tool (total comander, WinCompare, meld(linux), whatever...) The reason why I need a tool to generate difference report automatically from Fodler1 and Folder2 is simple - there are too much JARs in these Folders and I need to compare these folders (with next version of Jars) say 1 time in a month. So, I really do not want to do it manually at all!

Let's see what I've got so far:

1) I can find all JARs in each Folder:)

2) I can get the list of classes from each 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) There is Reflection in Java (Core Java 2 Volume I - Fundamentals, Example 5-5), so I can get the list of methods from one class once I know its name.

In order to do that I need to make an instance of each class, the problem is how can I make the instance of each Class which I got from each JAR file? Now I'm loading each 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 + "!/" ) );
  }

No exceptions, but I can not find any resource in it, trying to load the class like:

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

And getting "java.lang.ClassNotFoundException".

Any glue where is the problem? (class name is verified. it is hardcoded just for testing, ideally it should get it from the list of the classes)

Second question: since most of the classes in Folder1 and Folder2 will be same, what will happen if I load the same class second time (from Fodler2)?


Solution

  • This is not directly answering your question, however you may get a look to the ASM framework . This allows you to analyze bytecode without having to load the classes with the class loader. It is probably easier to do it this way.