Monday, May 04, 2009

That's Classy

Here's a simple program to report on Java .class versions. I'm sure some variant of this has been written a thousand times, but Google wouldn't give me what I wanted right away, so here it is again :)

The program takes one argument: a path to a .class file, .jar file, or directory containing a mixture of both, and produces a report of each class file's major .class format version (50 for Java 6, 49 for Java 5, and so on). Handy if you want to track down those new fangled classes and avoid the dreaded java.lang.UnsupportedClassVersionError

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public abstract class ThatsClassy {

static void classyFile(File file) throws Exception {
if (file.isDirectory())
for (File child: file.listFiles())
classyFile(child);
else if (file.getName().endsWith(".jar"))
classyJar(file);
else if (file.getName().endsWith(".class"))
classyClass(file.getPath(), new FileInputStream(file), true);
}

static void classyJar(File jarFile) throws Exception {
JarInputStream jarStream = new JarInputStream(new FileInputStream(jarFile));
JarEntry entry = jarStream.getNextJarEntry();
while (entry != null) {
if (entry.getName().endsWith(".class"))
classyClass(jarFile.getName() + "#" + entry.getName(), jarStream, false);
entry = jarStream.getNextJarEntry();
}
jarStream.close();
}

static void classyClass(String id, InputStream in, boolean close) throws Exception {
in.skip(7);
int majorClassVersion = in.read();
if (close) in.close();
System.out.println(id + " " + majorClassVersion);
}

public static void main(String[] args) throws Exception {
classyFile(new File(args[0]));
}
}