04 octubre 2007

Como saber con qué JDK se ha compilado una clase Java

Me he encontrado con una clase Java de la que no tenía ni idea de con qué JDK había sido compilada, y ante la alternativa de tener que probar con varios hasta conseguir el mínimo en que funciona, he encontrado este truco para mostrar la versión de especificación y qué JDK mínimo se necesita.
El código de la clase, que dejo aquí anotado para futuras referencias:

import java.io.*;

public class Version {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println("Usage: java version <.class file>");
System.exit(1);
}

if (! new File(args[0]).exists()) {
System.err.println(args[0] + " does not exist!");
System.exit(2);
}

DataInputStream dis = new DataInputStream(
new FileInputStream(args[0]));
int magic = dis.readInt();
if (magic != 0xcafebabe) {
System.err.println(args[0] + " is not a .class file");
System.exit(3);
}

int minor = dis.readShort();
int major = dis.readShort();
System.out.println("class file version is " + major + "." + minor);

String version = null;

if (major < 48) {
version = "1.3.1";
} else if (major == 48) {
version = "1.4.2";
} else if (major == 49) {
version = "1.5";
} else if (major == 50) {
version = "6";
} else {
version = "7";
}
System.out.println("You need to use JDK " + version + " or above");
}
}

2 comentarios:

David dijo...

O directamente, desde el directorio donde se encuentra el .class

Por ejemplo, la clase Test.class
definida en el paquete
com.foo.client.project
la encontraríamos en:

C:\proyecto\bin\com\foo\client\javap -verbose Test

y como resultado muestra:
SourceFile: "Test.java"
minor version: 0
major version: 50


En base a la tabla descubrimos su version:
<48 Requires JRE 1.3.1 or later
=48 Requires JRE 1.4.2 or later
=49 Requires JRE 1.5 or later
=50 Requires JRE 6 or later
>50 Requires JRE 7 or later

Unknown dijo...

Si, muy útil el javap.
La invocación correcta sería

c:\proyecto\bin\$ javap -verbose com.foo.client.project.Test

Hay que poner el nombre completo de la clase, e invocarla desde el directorio a partir del cual están los subdirectorios de los paquetes.