¿Cómo puedo saber qué versión del compilador de Java se usó para construir un jar? Tengo un archivo jar, y podría haber sido construido en cualquiera de los tres JDK. Necesitamos saber exactamente cuál, para poder certificar la compatibilidad. ¿La versión del compilador está incrustada en algún lugar de los archivos de clase o jar?
212
Created-By: 1.7.0_13 (Oracle Corporation)
Created-By: Apache Maven
yBuild-Jdk: 1.8.0_25
Respuestas:
No se puede distinguir del archivo JAR en sí, necesariamente.
Descargue un editor hexadecimal y abra uno de los archivos de clase dentro del JAR y observe las compensaciones de bytes 4 a 7. La información de la versión está integrada.
http://en.wikipedia.org/wiki/Java_class_file
Nota: Como se menciona en el comentario a continuación,
fuente
A
jar
es simplemente un contenedor. Es un archivo de archivo a latar
. Si bienjar
puede tener información interesante dentro de su jerarquía META-INF , no tiene la obligación de especificar la antigüedad de las clases dentro de su contenido. Para eso, uno debe examinar losclass
archivos allí.Como Peter Lawrey mencionó en el comentario a la pregunta original, no necesariamente puede saber qué versión de JDK creó un
class
archivo determinado , pero puede encontrar la versión de clase de código de byte delclass
archivo contenido en ajar
.Sí, esto apesta, pero el primer paso es extraer una o más clases del
jar
. Por ejemplo:En Linux, Mac OS X o Windows con Cygwin instalado, el comando file (1) conoce la versión de la clase.
O, alternativamente, usar
javap
desde el JDK como @ jikes.thunderbolt señala acertadamente:Y si está relegado a un
Windows
entorno sinfile
ogrep
FWIW, coincidiré en que
javap
contará mucho más sobre unclass
archivo dado que la pregunta original formulada.De todos modos, una versión de clase diferente, por ejemplo:
El número principal de la versión de clase corresponde a las siguientes versiones de Java JDK:
fuente
file
no demostró que, pero yo era capaz de comprobar la clase de forma manual con este comando:hexdump ~/bin/classes/P.class | head
. Solo mire el octavo byte y conviértalo a decimal.JAR=something.jar ; unzip -p $JAR `unzip -l $JAR | grep '\.class$' | head -1` | file -
file file.class
(5.22-1) no mostró el objetivo de la clase java inicialmente: "file.class: [architecture = 6909806] [architecture = 6845039]". Sin embargo,file -k file.class
hizo eso: "file.class: [architecture = 6909806] [architecture = 6845039] compiló datos de clase Java, versión 50.0 (Java 1.6)". Parece quefile
solo obtuvo la primera coincidencia en sus archivos mágicos db sin-k
.Aquí está la forma en que Java encuentra esta información.
Windows:
javap -v <class> | findstr major
Unix:
javap -v <class> | grep major
Por ejemplo:
> javap -v Application | findstr major major version: 51
fuente
<class>
parámetro?Application.class
archivo y resultó estar compilado para Java 7 (major version: 51
).javac
versión que compiló los archivos .class, que es lo que se solicitó.No es necesario descomprimir el JAR (si se conoce o se busca uno de los nombres de clase, por ejemplo, usando 7zip), por lo que en Windows lo siguiente sería suficiente:
fuente
javac
versión que compiló los archivos .class, que es lo que se solicitó.El compilador de Java (
javac
) no crea frascos, traduce los archivos de Java en archivos de clase. La herramienta Jar (jar
) crea los frascos reales. Si no se especificó ningún manifiesto personalizado, el manifiesto predeterminado especificará qué versión del JDK se usó para crear el jar.fuente
Como necesitaba analizar frascos gordos, estaba interesado en la versión de cada clase individual en un archivo jar. Por lo tanto, tomé el enfoque de Joe Liversedge https://stackoverflow.com/a/27877215/1497139 y lo combiné con la tabla de versiones de números de clase de David J. Liszewski ' https://stackoverflow.com/a/3313839/1497139 para crear un script bash jarv para mostrar las versiones de todos los archivos de clase en un archivo jar.
uso
Ejemplo
Bash script jarv
fuente
head -1
se puede usar junto con el script: por lo general, es suficiente ver la versión de la primera clase en el archivo jar.Puede encontrar la versión del compilador de Java a partir de archivos .class utilizando un Editor Hex.
Paso 1: extraiga los archivos .class del archivo jar con un extractor zip
Paso 2: abra el archivo .class con un editor hexadecimal (he utilizado el complemento de editor hexadecimal Notepad ++. Este complemento lee el archivo como binario y lo muestra en hexadecimal).
Los índices 6 y 7 proporcionan el número de versión principal del formato de archivo de clase utilizado. https://en.wikipedia.org/wiki/Java_class_file
Java SE 11 = 55 (0x37 hex)
Java SE 10 = 54 (0x36 hexadecimal)
Java SE 9 = 53 (0x35 hexadecimal)
Java SE 8 = 52 (0x34 hexadecimal),
Java SE 7 = 51 (0x33 hexadecimal),
Java SE 6.0 = 50 (0x32 hexadecimal),
Java SE 5.0 = 49 (0x31 hexadecimal),
JDK 1.4 = 48 (0x30 hexadecimal),
JDK 1.3 = 47 (0x2F hexadecimal),
JDK 1.2 = 46 (0x2E hexadecimal),
JDK 1.1 = 45 (0x2D hexadecimal).
fuente
Puede ver la versión binaria de Java inspeccionando los primeros 8 bytes (o utilizando una aplicación que pueda).
El compilador en sí mismo, a mi leal saber y entender, no inserta ninguna firma de identificación. De todos modos, no puedo detectar tal cosa en el formato de clase de especificación de VM de archivo .
fuente
javac
versión que compiló los archivos .class, que es lo que se solicitó.El código publicado por Owen puede brindarle la información mencionada por varias de las otras respuestas aquí:
Vea también este y este sitio. Terminé modificando el código de Mind Products rápidamente para verificar para qué se compiló cada una de mis dependencias.
fuente
javac
versión que compiló los archivos .class, que es lo que se solicitó.Los desarrolladores y administradores que ejecutan Bash pueden encontrar útiles estas prácticas funciones:
Puede pegarlos para usarlos una vez o agregarlos a
~/.bash_aliases
o~/.bashrc
. Los resultados se parecen a:y
EDITAR Como señala jackrabbit , no puede confiar 100% en el manifiesto para decirle nada útil. Si lo fuera, entonces podría sacarlo en su shell UNIX favorito con
unzip
:Este .jar no tiene nada útil en el manifiesto sobre las clases contenidas.
fuente
javac
versión que compiló los archivos .class, que es lo que se solicitó.One liner (Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
Esto imprime el contenido del
MANIFEST.MF
archivo en stdout (es de esperar que haya uno en su archivo jar :)Dependiendo de qué construyó su paquete, encontrará la versión JDK en
Created-By
oBuild-Jdk
clave.fuente
MANIFEST.MF
, así como tampoco hay obligación de que los valores sean correctos (Sí, una vez me encontré con un.jar
valor falso).javac
versión que compiló los archivos .class, que es lo que se solicitó.Cada archivo de clase tiene un número de versión incrustado para el nivel de código de bytes que la JVM usa para ver si le gusta ese fragmento de código de bytes en particular o no. Esto es 48 para Java 1.4, 49 para Java 1.5 y 50 para Java 6.
Existen muchos compiladores que pueden generar código de bytes en cada nivel, javac usa la opción "-target" para indicar qué nivel de código de bytes generar, y Java 6 javac puede generar código de bytes para al menos 1.4, 1.5 y 6. No creo que el compilador inserta cualquier cosa que pueda identificar al compilador en sí, que es lo que creo que pides. Además, el compilador Eclipse se usa cada vez más, ya que es un solo jar que solo puede ejecutarse con JRE.
En un archivo jar generalmente hay muchas clases, y cada una de ellas es independiente, por lo que debe investigar todas las clases en el jar para asegurarse de las características de los contenidos.
fuente
Siguiendo la respuesta de @David J. Liszewski, ejecuté los siguientes comandos para extraer el manifiesto del archivo jar en Ubuntu:
fuente
unzip -p LiceneSearch.jar META-INF/MANIFEST.MF
javac
versión que compiló los archivos .class, que es lo que se solicitó.Muchas veces, es posible que esté viendo archivos jar completos o archivos war que contienen muchos archivos jar además de ellos.
Debido a que no quería verificar manualmente cada clase, escribí un programa Java para hacer eso:
https://github.com/Nthalk/WhatJDK
Si bien esto no dice con qué se compiló la clase, determina qué JDK podrá CARGAR las clases, que es probablemente con lo que quería comenzar.
fuente
Para ampliar las respuestas de Jonathon Faust y McDowell : Si está en un sistema basado en * nix, puede usar
od
(uno de los primeros programas Unix 1 que debería estar disponible prácticamente en todas partes) para consultar el.class
archivo a nivel binario:Esta es la salida los valores enteros familiares, por ejemplo,
50
paraJava 5
,51
porJava 6
y así sucesivamente.1 Cita de https://en.wikipedia.org/wiki/Od_(Unix)
fuente
javac
versión que compiló los archivos .class, que es lo que se solicitó.También escribí mi propio script bash para volcar la versión de Java requerida por todos los frascos pasados en la línea de comando ... El mío es un poco difícil, pero funciona para mí ;-)
ejemplo de uso
jar_dump_version_of_jvm_required.sh
fuente
Puede hacer esto fácilmente en la línea de comandos utilizando el siguiente proceso:
Si conoce alguno de los nombres de clase en jar, puede usar el siguiente comando:
ejemplo:
Salida:
Referencia rápida :
fuente
Verifica en el archivo de manifiesto del ejemplo jar:
Versión de manifiesto: 1.0 Creado por: 1.6.0 (IBM Corporation)
fuente
En Windows haga lo siguiente:
Ahora Eclipse mostrará la versión mayor y menor exacta.
fuente
Construyo un pequeño script bash (en github) basado en la sugerencia de Davids usando el
file
comandofuente