example java jar

javac example



¿Qué versión de javac construyó mi jar? (16)

¿Cómo puedo saber qué versión del compilador de Java se utilizó para construir un jar? 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?


Aquí está la forma de Java de encontrar esta información.

Windows: javap -v <class> | findstr major javap -v <class> | findstr major
Unix: javap -v <class> | grep major javap -v <class> | grep major

Por ejemplo:
> javap -v Application | findstr major major version: 51


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 lo hago Creo que el compilador inserta todo lo 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.


Construyo un pequeño script bash (en github) basado en la sugerencia de David usando el comando file


El código publicado por Owen puede decirle la información mencionada por varias 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 } }

Ver 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 compilador de Java ( javac ) no construye archivos jar, traduce archivos Java en archivos de clase. La herramienta Jar ( jar ) crea los tarros reales. Si no se especificó ningún manifiesto personalizado, el manifiesto predeterminado especificará qué versión del JDK se utilizó para crear el jar.


En Windows, haga lo siguiente:

  1. Descomprime o extrae el archivo JAR usando el comando WinZip / Java JAR.
  2. Arrastre y suelte uno de los archivos de clase en su proyecto Eclipse Java.
  3. Abra el archivo de clase.

Ahora Eclipse mostrará la versión mayor y menor exacta.


Los desarrolladores y administradores que ejecutan Bash pueden encontrar útiles estas funciones de conveniencia:

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 pegarlos para usarlos una sola vez o agregarlos a ~/.bash_aliases o ~/.bashrc . Los resultados se ven 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 lo señala , no puedes confiar 100% en el manifiesto para decirte algo útil. Si fuera así, puedes sacarlo en tu shell UNIX favorito 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 sobre las clases contenidas.


Muchas veces, es posible que esté mirando archivos jar completos o archivos war que contienen muchos archivos jar además de ellos mismos.

Como no quería verificar manualmente cada clase, escribí un programa de 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 con qué se compiló la clase, determina qué JDK podrá CARGAR las clases, que es probablemente con lo que quería comenzar.


No es necesario descomprimir el JAR (si se conoce uno de los nombres de clase o se busca, por ejemplo, utilizando 7zip), por lo que en Windows sería suficiente:

javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major


No se puede decir desde el archivo JAR, necesariamente.

Descargue un editor hexadecimal y abra uno de los archivos de clase dentro del JAR y observe los desplazamientos de bytes 4 a 7. La información de la versión está incorporada.

http://en.wikipedia.org/wiki/Java_class_file

Nota: Como se menciona en el comentario a continuación,

esos bytes te dicen para qué versión se ha compilado la clase, no qué versión compiló.


Para ampliar McDowell''s respuestas de Jonathon Faust y McDowell''s : Si tiene un sistema basado en * nix, puede usar od (uno de los primeros programas de Unix 1 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

Esto dará como resultado los valores enteros familiares, por ejemplo, 50 para Java 5 , 51 para Java 6 y así sucesivamente.

1 cita de https://en.wikipedia.org/wiki/Od_(Unix)



Siguiendo la respuesta de @David J. Liszewski, ejecuté 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


Un jar es simplemente un contenedor. Es un archivo de archivo a la tar . Si bien un contenedor puede contener 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 sus contenidos. Para eso, uno debe examinar los archivos de class mismo.

Tal como lo mencionó Peter Lawrey en el comentario de la pregunta original, no necesariamente puede saber qué versión de JDK compiló un archivo de class determinado, pero puede averiguar la versión de la class código de bytes del archivo de class contenido en un contenedor.

Sí, esto apesta, 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 clase.

$ file ./org/apache/log4j/Appender.class ./org/apache/log4j/Appender.class: compiled Java class data, version 45.3

O alternativamente, usando javap del JDK como @ jikes.thunderbolt acertadamente señala:

$ javap -v ./org/apache/log4j/Appender.class | grep major major version: 45

Y si está relegado a un entorno de Windows sin 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 un archivo de class determinado 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

El número principal de la versión de clase 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

Un trazador de líneas (Linux)

unzip -p mylib.jar META-INF/MANIFEST.MF

Esto imprime el contenido del archivo MANIFEST.MF en stdout (esperemos que haya uno en su archivo jar :)

Dependiendo de qué construyó su paquete, encontrará la versión JDK en la clave Created-By o Build-Jdk .


Usted marca el archivo Manifiesto del ejemplo jar:

Manifest-Version: 1.0 Created-By: 1.6.0 (IBM Corporation)