Tool zum Lesen und Anzeigen von Java .class-Versionen
-
09-06-2019 - |
Frage
Kennt jemand von euch ein Tool, das nach .class-Dateien sucht und dann deren kompilierte Versionen anzeigt?
Ich weiß, dass Sie sie einzeln in einem Hex-Editor betrachten können, aber ich muss viele Klassendateien durchsehen (irgendetwas in meiner riesigen Anwendung kompiliert aus irgendeinem Grund nach Java6).
Lösung
Benutzen Sie die Javap Tool, das mit dem JDK geliefert wird.Der -verbose
Option gibt die Versionsnummer der Klassendatei aus.
> javap -verbose MyClass
Compiled from "MyClass.java"
public class MyClass
SourceFile: "MyClass.java"
minor version: 0
major version: 46
...
Um nur die Version anzuzeigen:
WINDOWS> javap -verbose MyClass | find "version"
LINUX > javap -verbose MyClass | grep version
Andere Tipps
Es ist leicht zu lesen Signatur der Klassendatei und erhalten Sie diese Werte ohne eine Drittanbieter-API.Sie müssen lediglich die ersten 8 Bytes lesen.
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
Für die Klassendateiversion 51.0 (Java 7) lauten die Anfangsbytes:
CA FE BA BE 00 00 00 33
...wobei 0xCAFEBABE die magischen Bytes sind, 0x0000 die Nebenversion und 0x0033 die Hauptversion ist.
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);
}
}
}
Wanderverzeichnisse (Datei) und Archive (JarFile) Die Suche nach Klassendateien ist trivial.
Oracles Joe Darcys Blog listet die auf Zuordnungen von Klassenversionen zu JDK-Versionen bis 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
Auf Unix-ähnlich
file /path/to/Thing.class
Gibt auch den Dateityp und die Version an.So sieht die Ausgabe aus:
kompilierte Java-Klassendaten, Version 49.0
Wenn Sie auf einem Unix-System arbeiten, können Sie einfach Folgendes tun:
find /target-folder -name \*.class | xargs file | grep "version 50\.0"
(Meine Version der Datei sagt „kompilierte Java-Klassendaten, Version 50.0“ für Java6-Klassen).
Noch eine Java-Versionsprüfung
od -t d -j 7 -N 1 ApplicationContextProvider.class | head -1 | awk '{print "Java", $2 - 44}'
Vielleicht hilft das auch jemandem.Es scheint, dass es eine einfachere Möglichkeit gibt, die JAVA-Version zum Kompilieren/Erstellen von .class zu verwenden.Diese Methode ist nützlich für die Selbstprüfung von Anwendungen/Klassen in der JAVA-Version.
Ich habe die JDK-Bibliothek durchgesehen und diese nützliche Konstante gefunden:com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION.Ich weiß nicht, seit wann es in JAVA JDK ist.
Wenn ich diesen Code für mehrere Versionskonstanten ausprobiere, erhalte ich das folgende Ergebnis:
Quelle:
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() );
Ausgabe:
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
Im Klassenbytecode ist tatsächlich eine Konstante gespeichert – siehe rot markierter Teil von Main.call – Konstante, gespeichert im .class-Bytecode
Die Konstante wird in der Klasse verwendet, um zu überprüfen, ob die JAVA-Version veraltet ist (siehe Wie Java prüft, ob es veraltet ist)...