Comment savoir quelle version du compilateur Java a été utilisée pour créer un bocal? J'ai un fichier jar, et il aurait pu être construit dans l'un des trois JDK. Nous devons savoir exactement lequel, afin de pouvoir certifier la compatibilité. La version du compilateur est-elle intégrée quelque part dans les fichiers de classe ou le bocal?
212
Created-By: 1.7.0_13 (Oracle Corporation)
Created-By: Apache Maven
etBuild-Jdk: 1.8.0_25
Réponses:
Vous ne pouvez pas dire à partir du fichier JAR lui-même, nécessairement.
Téléchargez un éditeur hexadécimal et ouvrez l'un des fichiers de classe à l'intérieur du JAR et examinez les décalages d'octets 4 à 7. Les informations de version sont intégrées.
http://en.wikipedia.org/wiki/Java_class_file
Remarque: Comme mentionné dans le commentaire ci-dessous,
la source
A
jar
n'est qu'un conteneur. Il s'agit d'une archive de fichiers à latar
. Même si unjar
peut contenir des informations intéressantes dans sa hiérarchie META-INF , il n'a aucune obligation de spécifier le millésime des classes dans son contenu. Pour cela, il faut examiner lesclass
fichiers qui s'y trouvent.Comme Peter Lawrey l'a mentionné dans le commentaire de la question d'origine, vous ne pouvez pas nécessairement savoir quelle version JDK a construit un
class
fichier donné , mais vous pouvez trouver la version de la classe de code octet duclass
fichier contenu dans ajar
.Oui, c'est un peu nul, mais la première étape consiste à extraire une ou plusieurs classes du
jar
. Par exemple:Sous Linux, Mac OS X ou Windows avec Cygwin installé, la commande file (1) connaît la version de la classe.
Ou bien, utiliser à
javap
partir du JDK comme @ jikes.thunderbolt indique avec justesse:Et si vous êtes relégué dans un
Windows
environnement sansfile
ougrep
FWIW, je conviens que
javap
cela en dira beaucoup plus sur une donnéeclass
fichier que la question initiale posée.Quoi qu'il en soit, une version de classe différente, par exemple:
Le numéro majeur de version de classe correspond aux versions JDK Java suivantes:
la source
file
ne montre pas, mais j'ai pu vérifier la classe manuellement avec cette commande:hexdump ~/bin/classes/P.class | head
. Regardez simplement le huitième octet et convertissez-le en décimal.JAR=something.jar ; unzip -p $JAR `unzip -l $JAR | grep '\.class$' | head -1` | file -
file file.class
(5.22-1) n'a pas montré la cible de classe Java initialement: "file.class: [architecture = 6909806] [architecture = 6845039]". Cependantfile -k file.class
, cela: "file.class: [architecture = 6909806] [architecture = 6845039] données de classe Java compilées, version 50.0 (Java 1.6)". On dirait qu'ilfile
n'a obtenu que le premier match dans sa base de données magicfiles sans-k
.Voici la façon dont Java trouve ces informations.
Windows:
javap -v <class> | findstr major
Unix:
javap -v <class> | grep major
Par exemple:
> javap -v Application | findstr major major version: 51
la source
<class>
paramètre?Application.class
fichier et il s'est avéré être compilé pour Java 7 (major version: 51
).javac
version qui a compilé les fichiers .class, ce qui était demandé.Il n'est pas nécessaire de décompresser le fichier JAR (si l'un des noms de classe est connu ou recherché, par exemple en utilisant 7zip), donc sous Windows, les éléments suivants seraient suffisants:
la source
javac
version qui a compilé les fichiers .class, ce qui était demandé.Le compilateur Java (
javac
) ne construit pas de fichiers JAR, il traduit les fichiers Java en fichiers de classe. L'outil Jar (jar
) crée les pots réels. Si aucun manifeste personnalisé n'a été spécifié, le manifeste par défaut spécifiera quelle version du JDK a été utilisée pour créer le bocal.la source
Comme j'avais besoin d'analyser des pots de graisse, j'étais intéressé par la version de chaque classe individuelle dans un fichier de pot. Par conséquent, j'ai adopté l'approche Joe Liversedge https://stackoverflow.com/a/27877215/1497139 et l' ai combinée avec la table de version du numéro de classe https://stackoverflow.com/a/3313839/1497139 de David J. Liszewski pour créer un script bash jarv pour afficher les versions de tous les fichiers de classe dans un fichier jar.
usage
Exemple
Bash script jarv
la source
head -1
peut être utilisé en conjonction avec le script: généralement, il suffit de voir la version de la première classe dans le fichier jar.vous pouvez trouver la version du compilateur Java à partir de fichiers .class à l'aide d'un éditeur hexadécimal.
Étape 1: Extraire les fichiers .class du fichier jar à l'aide d'un extracteur zip
étape 2: ouvrir le fichier .class avec un éditeur hexadécimal. (J'ai utilisé le plug-in de l'éditeur hexadécimal notepad ++. Ce plugin lit le fichier en binaire et l'affiche en hexadécimal) Vous pouvez voir ci-dessous.
Les index 6 et 7 indiquent le numéro de version principal du format de fichier de classe utilisé. 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 (0x30 hex),
JDK 1,3 = 47 (hex2F2),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (hex2D 0xD).
la source
Vous pouvez indiquer la version binaire Java en inspectant les 8 premiers octets (ou en utilisant une application qui le peut).
Le compilateur lui-même n'insère, à ma connaissance, aucune signature d'identification. Je ne peux pas repérer une telle chose dans le format de classe de fichier VM spec de toute façon.
la source
javac
version qui a compilé les fichiers .class, ce qui était demandé.Le code affiché par Owen peut vous indiquer les informations mentionnées par un certain nombre d'autres réponses ici:
Voir aussi ceci et ce site. J'ai fini par modifier le code Mind Products rapidement pour vérifier à quoi chacune de mes dépendances a été compilée.
la source
javac
version qui a compilé les fichiers .class, ce qui était demandé.Les développeurs et administrateurs exécutant Bash peuvent trouver ces fonctions pratiques utiles:
Vous pouvez les coller pour une utilisation unique ou les ajouter à
~/.bash_aliases
ou~/.bashrc
. Les résultats ressemblent à:et
EDIT Comme le souligne jackrabbit , vous ne pouvez pas vous fier à 100% au manifeste pour vous dire quoi que ce soit d'utile. Si c'est le cas, vous pouvez le retirer dans votre shell UNIX préféré avec
unzip
:Ce .jar n'a rien d'utile dans le manifeste sur les classes contenues.
la source
javac
version qui a compilé les fichiers .class, ce qui était demandé.Un liner (Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
Ceci imprime le contenu de
MANIFEST.MF
fichier sur stdout (j'espère qu'il y en a un dans votre fichier jar :)En fonction de ce qui a construit votre package, vous trouverez la version JDK dans
Created-By
ou laBuild-Jdk
clé.la source
MANIFEST.MF
, ainsi que pour les valeurs d'être correctes (Oui, j'ai déjà rencontré un.jar
où la valeur était fausse).javac
version qui a compilé les fichiers .class, ce qui était demandé.Chaque fichier de classe a un numéro de version incorporé pour le niveau de code octet que la JVM utilise pour voir si elle aime ou non ce bloc de code octet particulier. Il s'agit de 48 pour Java 1.4, 49 pour Java 1.5 et 50 pour Java 6.
De nombreux compilateurs existent qui peuvent générer du code d'octets à chaque niveau, javac utilise l'option "-target" pour indiquer le niveau de code d'octets à générer, et le javac Java 6 peut générer du code d'octets pour au moins 1.4, 1.5 et 6. Je ne le fais pas crois que le compilateur insère tout ce qui peut identifier le compilateur lui-même, ce que je pense que vous demandez. De plus, le compilateur Eclipse est de plus en plus utilisé, car il s'agit d'un seul pot qui ne peut fonctionner qu'avec le JRE.
Dans un fichier jar, il y a généralement de nombreuses classes, et chacune d'entre elles est indépendante, vous devez donc étudier toutes les classes du jar pour être certain des caractéristiques du contenu.
la source
Suite à la réponse de @David J. Liszewski, j'ai exécuté les commandes suivantes pour extraire le manifeste du fichier jar sur Ubuntu:
la source
unzip -p LiceneSearch.jar META-INF/MANIFEST.MF
javac
version qui a compilé les fichiers .class, ce qui était demandé.La plupart du temps, vous pouvez consulter des fichiers jar entiers ou des fichiers war contenant en plus d'eux-mêmes de nombreux fichiers jar.
Parce que je ne voulais pas vérifier manuellement chaque classe, j'ai écrit un programme java pour le faire:
https://github.com/Nthalk/WhatJDK
Bien que cela ne dise pas avec quoi la classe a été compilée, cela détermine quels JDK pourront CHARGER les classes, ce qui est probablement ce que vous vouliez commencer.
la source
Pour développer les réponses de Jonathon Faust et McDowell : Si vous êtes sur un système basé sur * nix, vous pouvez utiliser
od
(l'un des premiers programmes Unix 1 qui devrait être disponible pratiquement partout) pour interroger le.class
fichier au niveau binaire:Cela produira les valeurs entières familières, par exemple
50
pourJava 5
,51
pourJava 6
et ainsi de suite.1 Citation de https://en.wikipedia.org/wiki/Od_(Unix)
la source
javac
version qui a compilé les fichiers .class, ce qui était demandé.J'ai également écrit mon propre script bash pour vider la version Java requise par tous les pots passés en ligne de commande ... Le mien est un peu rude, mais fonctionne pour moi ;-)
exemple d'utilisation
jar_dump_version_of_jvm_required.sh
la source
Vous pouvez facilement le faire sur la ligne de commande en utilisant le processus suivant:
Si vous connaissez l'un des noms de classe dans jar, vous pouvez utiliser la commande suivante:
exemple :
Production :
Référence rapide :
la source
Vous archivez le fichier manifeste de l'exemple de jar:
Version du manifeste: 1.0 Créé par: 1.6.0 (IBM Corporation)
la source
Sous Windows, procédez comme suit:
Maintenant, Eclipse affichera la version exacte majeure et mineure.
la source
Je construis un petit script bash (sur github) basé sur la suggestion de David en utilisant la
file
commandela source