¿Cómo puedo saber qué versión del compilador de Java se utilizó para construir un contenedor? Tengo un archivo jar, y podría haber sido creado en cualquiera de los tres JDK. Necesitamos saber exactamente cuál, para que podamos certificar la compatibilidad. ¿La versión del compilador está incrustada en algún lugar de los archivos de clase o jar?¿Qué versión de javac construyó mi jar?
Respuesta
No se puede decir desde el archivo JAR, necesariamente.
descargar un editor hexadecimal y abrir uno de los archivos de clase dentro de la jarra y mirar desplazamientos de bytes 4 a 7. Se construyó la información de versión en
http://en.wikipedia.org/wiki/Java_class_file
. Nota: Como se ha mencionado en el comentario a continuación,
esos bytes le dicen para qué versión se ha compilado la clase FOR, no qué versión compiló.
Para ser pedante, esos bytes te dicen para qué versión se ha compilado la clase, no qué versión compilada. Java le permite compilar código para que sea compatible con versiones anteriores de Java. Sin embargo, esto solo se aplica al código de bytes y al formato. Felizmente compilará código que hace referencia a bibliotecas JDK 6 en un formato JDK 5, por ejemplo. El JDK 5 cargará la clase, pero no puede ejecutarla ya que la biblioteca JDK 5 no tiene el código al que se hace referencia desde JDK 6. –
Podríamos encontrarlo en el archivo de manifiesto como Creado por: 1.7.0_21-b11 (Oracle Corporation) – Krishna
** [La otra respuesta] (http://stackoverflow.com/a/3313839/641451) le dice cómo hacer una fácil verificación a través de la línea de comando ** – mgarciaisaia
le puede decir la versión binaria de Java por inspecting the first 8 bytes (o usando un app que puede).
El compilador en sí no incluye, a mi leal saber y entender, ninguna firma de identificación. No puedo detectar tal cosa en el archivo VM spec class format de todos modos.
El compilador de Java (javac
) no crea archivos jar, traduce archivos Java en archivos de clase. La herramienta Jar (jar
) crea las jarras reales. Si no se especificó ningún manifiesto personalizado, el manifiesto predeterminado especificará qué versión del JDK se utilizó para crear el jar.
Si bien es cierto, esto no proporciona una respuesta a la pregunta. – zb226
@ zb226 AFAIK la versión del compilador utilizado para compilar las clases no puede obtenerse de los archivos de clase, solo la versión que las clases fueron compiladas _for_. La información que proporcioné proporciona la única información (estándar) que está disponible sobre la versión que construyó el artefacto. Si eso no es lo que se pregunta, la pregunta debe reformularse. – jackrabbit
OK, estaba viendo eso desde un punto de vista pragmático, pero veo tu punto ahora, se eliminó el voto negativo :) – zb226
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 inserte nada que pueda identificar al compilador, que es lo que creo que usted solicita. Además, cada vez se utiliza más el compilador Eclipse, ya que se trata de un único contenedor que solo se puede ejecutar 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 contenedor para asegurarse de las características de los contenidos.
A jar
es simplemente un contenedor. Es un archivo de archivo ā la tar
. Mientras que un jar
puede tener información interesante contenida dentro de su jerarquía META-INF, no tiene obligación de especificar la antigüedad de las clases dentro de sus contenidos. Para eso, uno debe examinar los archivos class
en el mismo.
Como como Peter Lawrey mencionados en el comentario a la pregunta original, no necesariamente puede saber qué versión del JDK construyó una class
archivo determinado, pero se puede averiguar la versión de la clase de código de bytes del archivo class
contenida en un jar
.
Sí, esto es una mierda, pero el primer paso es extraer una o más clases del jar
.Por ejemplo:
$ jar xf log4j-1.2.15.jar
En Linux, Mac OS X o Windows con Cygwin instalado, el comando file(1) conoce la versión de la clase.
$ file ./org/apache/log4j/Appender.class
./org/apache/log4j/Appender.class: compiled Java class data, version 45.3
O, alternativamente, utilizando javap
desde el JDK como @ jikes.thunderbolt acertadamente señala:
$ javap -v ./org/apache/log4j/Appender.class | grep major
major version: 45
Y si son relegados a un medio ambiente sin que ninguna de Windows
file
o grep
> javap -v ./org/apache/log4j/Appender.class | findstr major
major version: 45
FWIW, coincidiré en que javap
contará mucho más sobre undadoarchivo que la pregunta original.
De todos modos, una versión de clase diferente, por ejemplo:
$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0
La versión de la clase mayor número corresponde a las siguientes versiones Java JDK:
- 45,3 = Java 1,1
- 46 = Java 1.2
- 47 = Java 1.3
- 48 = Java 1.4
- 49 = Java 5
- 50 = Java 6
- 51 = Java 7
- 52 = Java 8
- 53 = Java 9
Mi versión de 'archivo' no lo mostró, pero pude verificar la clase manualmente con este comando: 'hexdump ~/bin/classes/P.class | cabeza'. Solo mira el octavo byte y conviértete en decimal. –
FYI 'archivo' parece depender de la versión de Java en cuanto a si también mostrará la versión JDK. en CentOS/Oracle Linux y una clase Java compilado 6 consigo "datos compilados de clase Java, versión 50.0 (Java 1.6)" pero cuando lo ejecuto en una clase compilada con Java 7 Acabo de obtener la versión genérica "datos compilados de la clase Java, versión 51.0" –
'' JAR = something.jar; descomprimir -p $ JAR 'unzip -l $ JAR | grep '\ .class $' | cabeza -1' | file -'' –
El code posted by Owen puede indicarle la información mencionada por una número de las otras respuestas aquí:
public void simpleExample()
{
FileInputStream fis = new FileInputStream ("mytest.class");
parseJavaClassFile (fis);
}
protected void parseJavaClassFile (InputStream classByteStream) throws Exception
{
DataInputStream dataInputStream = new DataInputStream (classByteStream);
magicNumber = dataInputStream.readInt();
if (magicNumber == 0xCAFEBABE)
{
int minorVer = dataInputStream.readUnsignedShort();
int majorVer = dataInputStream.readUnsignedShort();
// do something here with major & minor numbers
}
}
Véase también this y this sitio. Terminé modificando el código de Mind Products rápidamente para verificar para qué se compilaba cada una de mis dependencias.
El seguimiento de la respuesta de @ David J. Liszewski, me encontré con los siguientes comandos para extraer el manifiesto del archivo jar en Ubuntu:
# Determine the manifest file name:
$ jar tf LuceneSearch.jar | grep -i manifest
META-INF/MANIFEST.MF
# Extract the file:
$ sudo jar xf LuceneSearch.jar META-INF/MANIFEST.MF
# Print the file's contents:
$ more META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b30 (Oracle Corporation)
Main-Class: org.wikimedia.lsearch.config.StartupManager
O, como una línea: 'descomprime -p LiceneSearch.jar META-INF/MANIFEST.MF' –
En Windows haga lo siguiente:
- Descomprimir o extracto el archivo JAR utilizando el comando WinZip/Java JAR.
- Arrastre y suelte uno de los archivos de clase en su proyecto Eclipse Java.
- Abra el archivo de clase.
Ahora Eclipse mostrará la versión mayor y menor exacta.
Aquí está la manera de Java de encontrar esta información.
de Windows: javap -v <class> | findstr major
Unix: javap -v <class> | grep major
Por ejemplo:
> javap -v Application | findstr major major version: 51
de todas las respuestas dadas, tu respuesta es la más concisa y no implica escribir 10 líneas de código para conocer la versión información. +1 para eso –
¿Para qué sirve el parámetro '
@Dims El archivo ".class" que está tratando de encontrar la versión de. En su ejemplo, tiene un archivo 'Application.class' y resultó ser compilado para Java 7 (' versión principal: 51'). – inanutshellus
Los desarrolladores y administradores que ejecutan Bash pueden encontrar estas funciones de confort votos:
jar_jdk_version() {
[[ -n "$1" && -x "`command -v javap`" ]] && javap -classpath "$1" -verbose $(jar -tf "$1" | grep '.class' | head -n1 | sed -e 's/\.class$//') | grep 'major version' | sed -e 's/[^0-9]\{1,\}//'
}
print_jar_jdk_version() {
local version
version=$(jar_jdk_version "$1")
case $version in 49) version=1.5;; 50) version=1.6;; 51) version=1.7;; 52) version=1.8;; esac
[[ -n "$version" ]] && echo "`basename "$1"` contains classes compiled with JDK version $version."
}
Puede pegar para el uso de una sola vez o agregar a ~/.bash_aliases
o ~/.bashrc
. Los resultados parecen algo así como:
$ jar_jdk_version poi-ooxml-3.5-FINAL.jar
49
y
$ print_jar_jdk_version poi-ooxml-3.5-FINAL.jar
poi-ooxml-3.5-FINAL.jar contains classes compiled with JDK version 1.5.
EDITAR Como jackrabbit puntos cabo, no se puede confiar 100% en el manifiesto que le diga algo útil. Si lo fuera, entonces se podría tirar de él hacia fuera en su favorito de shell UNIX con unzip
:
$ unzip -pa poi-ooxml-3.5-FINAL.jar META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 11.3-b02 (Sun Microsystems Inc.)
Built-By: yegor
Specification-Title: Apache POI
Specification-Version: 3.5-FINAL-20090928
Specification-Vendor: Apache
Implementation-Title: Apache POI
Implementation-Version: 3.5-FINAL-20090928
Implementation-Vendor: Apache
Este .jar no tiene nada útil en el manifiesto de las clases contenidas.
construyo un poco de escritura del golpe (on github) basado en la sugerencia Davids con el comando file
Un forro (Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
Esto imprime el contenido de MANIFEST.MF
archivo a la salida estándar (esperemos que no existe uno en su archivo jar :)
Dependiendo de lo que creó su paquete, encontrará la versión JDK en Created-By
o Build-Jdk
clave.
Tenga en cuenta que no hay obligación de que estos campos estén presentes en 'MANIFEST.MF', así como que no hay obligación de que los valores sean correctos (Sí, una vez encontré un' .jar' donde el valor era falso). – zb226
Muchas veces, es posible que esté mirando archivos jar completos, o archivos war que contienen muchos archivos jar además de ellos mismos.
Debido a que no quería comprobar a mano cada clase, escribí un programa Java para hacer eso:
https://github.com/Nthalk/WhatJDK
./whatjdk some.war
some.war:WEB-INF/lib/xml-apis-1.4.01.jar contains classes compatible with Java1.1
some.war contains classes compatible with Java1.6
Si bien esto no dice lo que la clase fue compilado con, determina qué JDK podrá cargar las clases, que es probablemente con lo que quería comenzar.
No es necesario desempaquetar el JAR (si uno de los nombres de clase se conoce o se busca, p.usando 7zip), por lo que en Windows la siguiente sería suficiente:
javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
Esto también funciona en Linux (excepto que usaría grep en lugar de findstr, por supuesto) –
Para ampliar Jonathon Faust'sMcDowell's y respuestas: Si estás en un sistema basado en * nix, puede utilizar od
(uno de los primeros programas Unix que debería estar disponible prácticamente en todas partes) para consultar el archivo .class
en un nivel binario:
od -An -j7 -N1 -t dC SomeClassFile.class
Esta es la salida de los valores enteros conocidos, por ejemplo, 50
para Java 5
, 51
para Java 6
y así sucesivamente.
Presupuesto de https://en.wikipedia.org/wiki/Od_(Unix)
- 1. ¿Por qué Jar ignora mi manifiesto?
- 2. ¿Cómo hacer que javac encuentre archivos JAR? (Eclipse puede verlos)
- 3. ¿Cómo importo jar a mi programa java?
- 4. Configuración de la versión de destino de Java en ant javac
- 5. javac no se reconoce
- 6. Java - ¿Qué versión tenía un archivo .jar también?
- 7. ¿Qué versión es mi servidor MySQL?
- 8. ¿Por qué javac checkcast arrays dos veces?
- 9. Identificar mi versión dotnet
- 10. ¿Por qué .Net importa cuando se construyó un ensamblaje?
- 11. NoClassDefFoundError al intentar ejecutar mi jar con java.exe -jar ... ¿qué pasa?
- 12. ¿Qué versión de .NET usa mi script de PowerShell?
- 13. ¿Cómo incluyo archivos JAR externos en mi propio proyecto JAR
- 14. ¿Cómo puedo ver qué versión de JavaScript usa mi navegador?
- 15. Error al usar javac: "javac: indicador no válido: -s"
- 16. lectura Manifiesto de mi propia Jar
- 17. ¿Cómo puedo configurar mi Cygwin PATH para encontrar javac?
- 18. ant buildfile setting ubicación javac
- 19. ¿Cómo puedo ver mi versión de Eclipse?
- 20. ¿Qué versión de Safari corresponde a qué versión de WebKit?
- 21. Cómo agregar varios archivos .jar en la ruta de la clase javac/java - para Debian Linux
- 22. Clojure: ¿Cómo ejecutar mi main desde jar?
- 23. ¿Falta XMLReader en mi versión de PHP?
- 24. ¿cuál es mi versión HAProxy?
- 25. ¿Puedo encontrar qué destino .NET dll se construyó buscando en el archivo?
- 26. ClassPath en hormiga para la tarea javac
- 27. ¿Por qué javac se queja de la variable no inicializada?
- 28. Más rápido javac/ant?
- 29. Git: Administrar cada versión de mi aplicación?
- 30. ¿Cómo puedo degradar mi versión de SDK?
Usted puede decir la mayor Verson mirando el archivo de manifiesto. Puede decir la versión de destino mirando los archivos de clase, pero los JDK pueden producir archivos de clase para versiones anteriores de Java utilizando la opción -target, por lo que mirar los primeros bytes puede no ser preciso. –
En MANIFEST.MF puede encontrar algo como 'Created-By: 1.7.0_13 (Oracle Corporation)' – hko19
Parece que Maven 3 hace esto 'Created-By: Apache Maven' y' Build-Jdk: 1.8.0_25' –