2008-08-25 19 views
103

¿Alguno de ustedes conoce una herramienta que buscará archivos .class y luego mostrará sus versiones compiladas?Herramienta para leer y visualizar versiones .class de Java

Sé que puede verlos individualmente en un editor hexadecimal, pero tengo muchos archivos de clase para revisar (algo en mi aplicación gigante está compilando para Java6 por algún motivo).

+0

duplicado más populares http://stackoverflow.com/questions/1096148/how-to-check-the -jdk-version-used-to-compile-a-class-file tiene como respuesta algunas herramientas útiles que no se mencionan aquí. – Vadzim

Respuesta

129

Utilice la herramienta de javap que viene con el JDK. La opción -verbose imprimirá el número de versión del archivo de clase.

> javap -verbose MyClass 
Compiled from "MyClass.java" 
public class MyClass 
    SourceFile: "MyClass.java" 
    minor version: 0 
    major version: 46 
... 

para mostrar sólo la versión:

WINDOWS> javap -verbose MyClass | find "version" 
LINUX > javap -verbose MyClass | grep version 
39

Es bastante fácil leer el class file signature y obtener estos valores sin una API de terceros. Todo lo que necesita hacer es leer los primeros 8 bytes.

ClassFile { 
    u4 magic; 
    u2 minor_version; 
    u2 major_version; 

Para la versión de archivo de clase 51.0 (Java 7), los bytes de apertura son:

CA FE BA BE 00 00 00 33 

... donde 0xCAFEBABE son los bytes mágicas, 0x0000 es la versión menor y 0x0033 es la versión principal .

import java.io.*; 

public class Demo { 
    public static void main(String[] args) throws IOException { 
    ClassLoader loader = Demo.class.getClassLoader(); 
    try (InputStream in = loader.getResourceAsStream("Demo.class"); 
     DataInputStream data = new DataInputStream(in)) { 
     if (0xCAFEBABE != data.readInt()) { 
     throw new IOException("invalid header"); 
     } 
     int minor = data.readUnsignedShort(); 
     int major = data.readUnsignedShort(); 
     System.out.println(major + "." + minor); 
    } 
    } 
} 

directorios de caminata (File) y archivos (JarFile) en busca de archivos de clase es trivial.

Joe Darcy's blog listas de Oracle el class version to JDK version mappings hasta Java 7:

Target Major.minor Hex 
1.1  45.3  0x2D 
1.2  46.0  0x2E 
1.3  47.0  0x2F 
1.4  48.0  0x30 
5 (1.5) 49.0  0x31 
6 (1.6) 50.0  0x32 
7 (1.7) 51.0  0x33 
8 (1.8) 52.0  0x34 
9  53.0  0x35 
+0

Recuerde también que assert solo se ejecuta si está habilitado al iniciar Java para poder leer archivos basura si no está utilizando IllegalArgumentException (por ejemplo) – jontejj

9

Si usted está en un sistema UNIX que sólo podría hacer un

find /target-folder -name \*.class | xargs file | grep "version 50\.0" 

(mi versión de archivo dice "compila datos de la clase

Java , versión 50.0 "para clases java6).

+0

En macOS (10.12.6 al menos), la salida es aún más útil: archivo '* .class' produce: ' nombredeclase.class: datos de clases Java, versión 50.0 (Java 1.6) ' – Gary

17

En Unix-como

file /path/to/Thing.class

daré el tipo de archivo y la versión también. Esto es lo que la salida se ve como:

datos de la clase de Java compilados, versión 49,0

+0

(simplificado de la respuesta de WMR) – phunehehe

+0

esto es mucho más simple que las otras soluciones – mmuller

5

Sin embargo, otra versión de Java Ver

od -t d -j 7 -N 1 ApplicationContextProvider.class | head -1 | awk '{print "Java", $2 - 44}' 
4

en Eclipse si usted no tiene fuentes adjuntas. Tenga en cuenta la primera línea después de adjuntar el botón de fuente.

// compilado a partir de CDestinoLog.java (versión 1.5: 49,0, muy poco)

enter image description here

2

Tal vez esto ayude a alguien, también. Parece que hay una forma más fácil de obtener la versión JAVA utilizada para compilar/construir .class.De esta manera es útil para la autocomprobación de clase/aplicación en la versión de JAVA.

que han pasado por la biblioteca JDK y encontrado esta constante útil: com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION. No sé desde cuándo está en JAVA JDK.

Tratando este pedazo de código para varias constantes versión que recibo como resultado a continuación:

src:

System.out.println("JAVA DEV  ver.: " + com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION); 
System.out.println("JAVA RUN  v. X.Y: " + System.getProperty("java.specification.version")); 
System.out.println("JAVA RUN v. W.X.Y.Z: " + com.sun.deploy.config.Config.getJavaVersion()); //_javaVersionProperty 
System.out.println("JAVA RUN full ver.: " + System.getProperty("java.runtime.version") + " (may return unknown)"); 
System.out.println("JAVA RUN  type: " + com.sun.deploy.config.Config.getJavaRuntimeNameProperty()); 

de salida:

JAVA DEV  ver.: 1.8.0_77 
JAVA RUN  v. X.Y: 1.8 
JAVA RUN v. W.X.Y.Z: 1.8.0_91 
JAVA RUN full ver.: 1.8.0_91-b14 (may return unknown) 
JAVA RUN  type: Java(TM) SE Runtime Environment 

En el código de bytes de clases no es realmente constante almacenada - vea la parte roja marcada de Main.call - constant stored in .class bytecode

constante está en la clase utilizada para comprobar si la versión de Java no está actualizado (ver How Java checks that is out of date) ...

Cuestiones relacionadas