Wie kann ich feststellen, mit welcher Version des Java-Compilers ein JAR erstellt wurde? Ich habe eine JAR-Datei, die in einem von drei JDKs erstellt werden könnte. Wir müssen genau wissen, welche, damit wir die Kompatibilität zertifizieren können. Ist die Compilerversion irgendwo in den Klassendateien oder im JAR eingebettet?
212
Created-By: 1.7.0_13 (Oracle Corporation)
Created-By: Apache Maven
undBuild-Jdk: 1.8.0_25
Antworten:
Sie können es nicht unbedingt anhand der JAR-Datei selbst erkennen.
Laden Sie einen Hex-Editor herunter, öffnen Sie eine der Klassendateien in der JAR und sehen Sie sich die Byte-Offsets 4 bis 7 an. Die Versionsinformationen sind integriert.
http://en.wikipedia.org/wiki/Java_class_file
Hinweis: Wie im Kommentar unten erwähnt,
quelle
A
jar
ist nur ein Behälter. Es ist ein Dateiarchiv à latar
. Während ajar
möglicherweise interessante Informationen in seiner META-INF- Hierarchie enthält, ist es nicht verpflichtet, den Jahrgang der Klassen in seinem Inhalt anzugeben. Dazu muss man dieclass
darin enthaltenen Dateien untersuchen .Wie Peter Lawrey im Kommentar zur ursprünglichen Frage erwähnt hat, können Sie nicht unbedingt wissen, welche JDK-Version eine bestimmte
class
Datei erstellt hat, aber Sie können die Bytecode-Klassenversion derclass
in a enthaltenen Datei herausfindenjar
.Ja, das ist ein bisschen scheiße, aber der erste Schritt besteht darin, eine oder mehrere Klassen aus dem zu extrahieren
jar
. Beispielsweise:Unter Linux, Mac OS X oder Windows mit installiertem Cygwin kennt der Befehl file (1) die Klassenversion.
Alternativ kann die Verwendung
javap
aus dem JDK als @ jikes.thunderbolt treffend darauf hinweisen:Und wenn Sie in eine
Windows
Umgebung ohne entwederfile
oder verbannt sindgrep
FWIW, ich stimme zu, dass dies
javap
viel mehr über eine bestimmteclass
Datei aussagt als die ursprünglich gestellte Frage.Wie auch immer, eine andere Klassenversion, zum Beispiel:
Die Hauptnummer der Klassenversion entspricht den folgenden Java JDK-Versionen:
quelle
file
hat das nicht gezeigt, aber ich konnte die Klasse manuell mit diesem Befehl überprüfen :hexdump ~/bin/classes/P.class | head
. Schauen Sie sich einfach das achte Byte an und konvertieren Sie es in eine Dezimalzahl.JAR=something.jar ; unzip -p $JAR `unzip -l $JAR | grep '\.class$' | head -1` | file -
file file.class
(5.22-1) zeigte anfangs kein Java-Klassenziel: "file.class: [Architektur = 6909806] [Architektur = 6845039]". Diesfile -k file.class
geschah jedoch: "file.class: [Architektur = 6909806] [Architektur = 6845039] kompilierte Java-Klassendaten, Version 50.0 (Java 1.6)". Es sieht so aus, als hätte esfile
nur das erste Match in seiner Magicfiles-Datenbank ohne-k
.Hier ist Javas Weg, um diese Informationen zu finden.
Windows:
javap -v <class> | findstr major
Unix:
javap -v <class> | grep major
Beispielsweise:
> javap -v Application | findstr major major version: 51
quelle
<class>
Parameter?Application.class
Datei, die für Java 7 (major version: 51
) kompiliert wurde .javac
Version, mit der die .class-Dateien kompiliert wurden.Es ist nicht erforderlich, die JAR zu entpacken (wenn einer der Klassennamen bekannt ist oder beispielsweise mit 7zip nachgeschlagen wird), sodass unter Windows Folgendes ausreichen würde:
quelle
javac
Version, mit der die .class-Dateien kompiliert wurden.Der Java-Compiler (
javac
) erstellt keine Jars, sondern übersetzt Java-Dateien in Klassendateien. Das Jar-Tool (jar
) erstellt die eigentlichen Gläser. Wenn kein benutzerdefiniertes Manifest angegeben wurde, gibt das Standardmanifest an, welche Version des JDK zum Erstellen des JAR verwendet wurde.quelle
Da ich fette Gläser analysieren musste, interessierte ich mich für die Version jeder einzelnen Klasse in einer Glasdatei. Daher habe ich den Joe Liversedge-Ansatz https://stackoverflow.com/a/27877215/1497139 gewählt und ihn mit David J. Liszewskis https://stackoverflow.com/a/3313839/1497139 Klassennummer-Versionstabelle kombiniert , um ein Bash-Skript zu erstellen jarv, um die Versionen aller Klassendateien in einer JAR-Datei anzuzeigen.
Verwendung
Beispiel
Bash-Skript jarv
quelle
head -1
kann in Verbindung mit dem Skript verwendet werden: Normalerweise reicht es aus, die Version der ersten Klasse in der JAR-Datei zu sehen.Sie können die Java-Compilerversion aus .class-Dateien mit einem Hex-Editor finden.
Schritt 1: Extrahieren Sie .class-Dateien mit einem Zip-Extraktor aus der JAR-Datei
Schritt 2: Öffnen Sie die .class-Datei mit einem Hex-Editor. (Ich habe das Notepad ++ Hex-Editor-Plugin verwendet. Dieses Plugin liest die Datei als Binärdatei und zeigt sie in Hex an.) Sie können unten sehen.
Die Indizes 6 und 7 geben die Hauptversionsnummer des verwendeten Klassendateiformats an. https://en.wikipedia.org/wiki/Java_class_file
Java SE 11 = 55 (0x37 hex)
Java SE 10 = 54 (0x36 hex)
Java SE 9 = 53 (0x35 hex)
Java SE 8 = 52 (0x34 hex),
Java SE 7 = 51 (0x33 hex),
Java SE 6.0 = 50 (0x32 hex),
Java SE 5.0 = 49 (0x31 hex),
JDK 1,4 = 48 (0 × 30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1,2 = 46 (0 × 2E hex),
JDK 1.1 = 45 (0x2D hex).
quelle
Sie können die Java-Binärversion erkennen, indem Sie die ersten 8 Bytes überprüfen (oder eine App verwenden , die dies kann).
Der Compiler selbst fügt meines Wissens keine identifizierende Signatur ein. Ich kann so etwas sowieso nicht im Format der Datei- VM-Spezifikationsklasse erkennen .
quelle
javac
Version, mit der die .class-Dateien kompiliert wurden.Der von Owen gepostete Code kann Ihnen die Informationen mitteilen, die in einer Reihe anderer Antworten hier erwähnt werden:
Siehe auch diese und diese Seite. Am Ende habe ich den Mind Products-Code schnell geändert, um zu überprüfen, wofür jede meiner Abhängigkeiten kompiliert wurde.
quelle
javac
Version, mit der die .class-Dateien kompiliert wurden.Entwickler und Administratoren, die Bash ausführen, finden diese praktischen Funktionen möglicherweise hilfreich:
Sie können sie zur einmaligen Verwendung einfügen oder zu
~/.bash_aliases
oder hinzufügen~/.bashrc
. Die Ergebnisse sehen ungefähr so aus:und
BEARBEITEN Wie Jackrabbit betont , können Sie sich nicht zu 100% auf das Manifest verlassen, um Ihnen etwas Nützliches zu sagen. Wenn ja, können Sie es in Ihrer bevorzugten UNIX-Shell herausziehen mit
unzip
:Diese .jar-Datei enthält im Manifest nichts Nützliches zu den enthaltenen Klassen.
quelle
javac
Version, mit der die .class-Dateien kompiliert wurden.Ein Liner (Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
Dies druckt den Inhalt der
MANIFEST.MF
Datei nach stdout (hoffentlich gibt es einen in Ihrer JAR-Datei :)Je nachdem, was Ihr Paket erstellt hat, finden Sie die JDK-Version in
Created-By
oderBuild-Jdk
key.quelle
MANIFEST.MF
, und dass die Werte nicht korrekt sein müssen (Ja, ich bin einmal auf einen.jar
Wert gestoßen, bei dem der Wert falsch war).javac
Version, mit der die .class-Dateien kompiliert wurden.In jede Klassendatei ist eine Versionsnummer für die Bytecode-Ebene eingebettet, anhand derer die JVM prüft, ob sie diesen bestimmten Bytecode-Block mag oder nicht. Dies sind 48 für Java 1.4, 49 für Java 1.5 und 50 für Java 6.
Es gibt viele Compiler, die auf jeder Ebene Bytecode generieren können. Javac verwendet die Option "-target", um anzugeben, welche Bytecode-Ebene generiert werden soll, und Java 6-Javac kann Bytecode für mindestens 1.4, 1.5 und 6 generieren. Ich nicht Ich glaube, der Compiler fügt alles ein, was den Compiler selbst identifizieren kann. Ich denke, Sie fragen danach. Auch der Eclipse-Compiler wird zunehmend verwendet, da es sich um ein einzelnes JAR handelt, das nur mit der JRE ausgeführt werden kann.
In einer JAR-Datei gibt es normalerweise viele Klassen, von denen jede unabhängig ist. Daher müssen Sie alle Klassen in der JAR-Datei untersuchen, um sicherzugehen, welche Eigenschaften der Inhalt hat.
quelle
Nach der Antwort von @David J. Liszewski habe ich die folgenden Befehle ausgeführt, um das Manifest der JAR-Datei unter Ubuntu zu extrahieren:
quelle
unzip -p LiceneSearch.jar META-INF/MANIFEST.MF
javac
Version, mit der die .class-Dateien kompiliert wurden.Häufig sehen Sie sich ganze JAR-Dateien oder Kriegsdateien an, die neben sich selbst viele JAR-Dateien enthalten.
Da ich nicht jede Klasse von Hand überprüfen wollte, schrieb ich dazu ein Java-Programm:
https://github.com/Nthalk/WhatJDK
Dies sagt zwar nicht aus, mit was die Klasse kompiliert wurde, bestimmt jedoch, mit welchen JDKs die Klassen geladen werden können. Dies ist wahrscheinlich das, womit Sie beginnen wollten.
quelle
So erweitern Sie die Antworten von Jonathon Faust und McDowell : Wenn Sie auf einem * nix-basierten System arbeiten, können Sie
od
(eines der frühesten Unix-Programme 1, das praktisch überall verfügbar sein sollte) die.class
Datei auf Binärebene abfragen :Dies gibt die bekannten ganzzahligen Werte aus, z. B.
50
fürJava 5
,51
fürJava 6
und so weiter.1 Zitat aus https://en.wikipedia.org/wiki/Od_(Unix)
quelle
javac
Version, mit der die .class-Dateien kompiliert wurden.Ich habe auch mein eigenes Bash-Skript geschrieben, um die Java-Version zu sichern, die für alle an der Befehlszeile übergebenen Jars erforderlich ist ... Meins ist etwas rau, funktioniert aber für mich ;-)
Beispiel Verwendung
jar_dump_version_of_jvm_required.sh
quelle
Sie können dies einfach über die Befehlszeile mit folgendem Verfahren tun:
Wenn Sie einen der Klassennamen in jar kennen, können Sie den folgenden Befehl verwenden:
Beispiel:
Ausgabe :
Kurzübersicht :
quelle
Sie checken in der Manifest-Datei des JAR-Beispiels ein:
Manifest-Version: 1.0 Erstellt von: 1.6.0 (IBM Corporation)
quelle
Gehen Sie unter Windows wie folgt vor:
Jetzt zeigt Eclipse die genaue Haupt- und Nebenversion.
quelle
Ich erstelle ein kleines Bash-Skript (auf Github) basierend auf Davids Vorschlag mit dem
file
Befehlquelle