Como posso saber qual versão do compilador Java foi usada para criar um jar? Eu tenho um arquivo jar e poderia ter sido construído em qualquer um dos três JDKs. Precisamos saber exatamente qual deles, para que possamos certificar a compatibilidade. A versão do compilador está incorporada em algum lugar nos arquivos de classe ou jar?
212
Created-By: 1.7.0_13 (Oracle Corporation)
Created-By: Apache Maven
eBuild-Jdk: 1.8.0_25
Respostas:
Você não pode dizer pelo próprio arquivo JAR, necessariamente.
Faça o download de um editor hexadecimal e abra um dos arquivos de classe dentro do JAR e veja os desvios de bytes 4 a 7. As informações da versão estão embutidas.
http://en.wikipedia.org/wiki/Java_class_file
Nota: Conforme mencionado no comentário abaixo,
fonte
A
jar
é apenas um recipiente. É um arquivo de arquivo à latar
. Embora umjar
possa ter informações interessantes contidas em sua hierarquia META-INF , ele não tem obrigação de especificar o vintage das classes dentro de seu conteúdo. Para isso, é preciso examinar osclass
arquivos nele contidos.Como Peter Lawrey mencionou no comentário à pergunta original, você não pode necessariamente saber qual versão do JDK construiu um determinado
class
arquivo, mas pode descobrir a versão da classe de código de bytes doclass
arquivo contido em ajar
.Sim, isso meio que é péssimo, mas o primeiro passo é extrair uma ou mais classes do
jar
. Por exemplo:No Linux, Mac OS X ou Windows com o Cygwin instalado, o comando file (1) conhece a versão da classe.
Ou, alternativamente, usar
javap
do JDK como @ jikes.thunderbolt indica apropriadamente:E se você for relegado a um
Windows
ambiente sem umfile
ou outrogrep
FWIW, vou concordar que
javap
dirá muito mais sobre um determinadoclass
arquivo do que a pergunta original.Enfim, uma versão de classe diferente, por exemplo:
O número principal da versão da classe corresponde às seguintes versões do Java JDK:
fonte
file
não mostrar isso, mas eu era capaz de verificar a classe manualmente com o comando:hexdump ~/bin/classes/P.class | head
. Basta olhar para o oitavo byte e converter para decimal.JAR=something.jar ; unzip -p $JAR `unzip -l $JAR | grep '\.class$' | head -1` | file -
file file.class
(5.22-1) não mostrou o destino da classe java inicialmente: "file.class: [architecture = 6909806] [architecture = 6845039]". No entantofile -k file.class
, isso foi feito: "file.class: [architecture = 6909806] [architecture = 6845039] compilou dados da classe Java, versão 50.0 (Java 1.6)". Parece quefile
só conseguiu a primeira partida em seus arquivos mágicos db sem-k
.Aqui está o caminho do Java para encontrar essas informações.
Windows:
javap -v <class> | findstr major
Unix:
javap -v <class> | grep major
Por exemplo:
> javap -v Application | findstr major major version: 51
fonte
<class>
parâmetro?Application.class
arquivo e acabou sendo compilado para o Java 7 (major version: 51
).javac
versão que compilou os arquivos .class, que foi solicitado.Não é necessário descompactar o JAR (se um dos nomes de classe for conhecido ou consultado, por exemplo, usando 7zip), portanto, no Windows, o seguinte seria suficiente:
fonte
javac
versão que compilou os arquivos .class, que foi solicitado.O compilador Java (
javac
) não cria jars, converte arquivos Java em arquivos de classe. A ferramenta Jar (jar
) cria os frascos reais. Se nenhum manifesto customizado foi especificado, o manifesto padrão especificará qual versão do JDK foi usada para criar o jar.fonte
Como eu precisava analisar os frascos gordos, estava interessado na versão de cada classe individual em um arquivo jar. Portanto, adotei a abordagem de Joe Liversedge https://stackoverflow.com/a/27877215/1497139 e a combinei com a tabela de versão do número da classe https://stackoverflow.com/a/3313839/1497139 da classe de J. J. Liszewski para criar um script bash jarv para mostrar as versões de todos os arquivos de classe em um arquivo jar.
uso
Exemplo
Jarv do script Bash
fonte
head -1
pode ser usado em conjunto com o script: geralmente, é suficiente ver a versão da primeira classe no arquivo jar.você pode encontrar a versão do compilador Java nos arquivos .class usando um Editor Hex.
Etapa 1: extrair arquivos .class do arquivo jar usando um extrator zip
passo 2: abra o arquivo .class com um editor hexadecimal. (Eu usei o plug-in do editor hexadecimal do notepad ++. Este plug-in lê o arquivo como binário e mostra-o em hexadecimal) Você pode ver abaixo.
Os índices 6 e 7 fornecem o número da versão principal do formato de arquivo de classe que está sendo usado. 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 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).
fonte
Você pode informar a versão binária do Java inspecionando os primeiros 8 bytes (ou usando um aplicativo que pode).
O próprio compilador não insere, de acordo com o meu conhecimento, nenhuma assinatura de identificação. Não consigo identificar isso no formato de classe de especificação de arquivo VM .
fonte
javac
versão que compilou os arquivos .class, que foi solicitado.O código postado por Owen pode fornecer as informações mencionadas por várias das outras respostas aqui:
Veja também este e este site. Acabei modificando o código Mind Products rapidamente para verificar para que cada uma das minhas dependências foi compilada.
fonte
javac
versão que compilou os arquivos .class, que foi solicitado.Os desenvolvedores e administradores que executam o Bash podem achar úteis estas funções de conveniência:
Você pode colá-los para uso único ou adicioná-los a
~/.bash_aliases
ou~/.bashrc
. Os resultados são parecidos com:e
EDITAR Como o jackrabbit aponta, você não pode 100% confiar no manifesto para lhe dizer algo útil. Se fosse, você poderia retirá-lo em seu shell UNIX favorito com
unzip
:Este .jar não tem nada útil no manifesto sobre as classes contidas.
fonte
javac
versão que compilou os arquivos .class, que foi solicitado.Um forro (Linux)
unzip -p mylib.jar META-INF/MANIFEST.MF
Isso imprime o conteúdo do
MANIFEST.MF
arquivo no stdout (espero que exista um no seu arquivo jar :)Dependendo do que construiu seu pacote, você encontrará a versão
Created-By
ouBuild-Jdk
chave do JDK .fonte
MANIFEST.MF
, assim como não há obrigação de os valores estarem corretos (Sim, uma vez encontrei uma.jar
onde o valor era falso).javac
versão que compilou os arquivos .class, que foi solicitado.Cada arquivo de classe possui um número de versão incorporado ao nível do código de bytes que a JVM usa para verificar se gosta ou não desse pedaço de código de bytes específico. Isso é 48 para Java 1.4, 49 para Java 1.5 e 50 para Java 6.
Existem muitos compiladores que podem gerar código de byte em cada nível, o javac usa a opção "-target" para indicar qual nível de código de byte gerar e o javac Java 6 pode gerar código de byte para pelo menos 1.4, 1.5 e 6. Eu não acredito que o compilador insere qualquer coisa que possa identificar o próprio compilador, o que eu acho que você pede. Além disso, o compilador Eclipse está sendo cada vez mais utilizado, pois é um jar único que pode ser executado apenas com o JRE.
Em um arquivo jar geralmente há muitas classes, e cada uma delas é independente; portanto, você precisa investigar todas as classes na jar para ter certeza sobre as características do conteúdo.
fonte
Seguindo a resposta de @David J. Liszewski, executei os seguintes comandos para extrair o manifesto do arquivo jar no Ubuntu:
fonte
unzip -p LiceneSearch.jar META-INF/MANIFEST.MF
javac
versão que compilou os arquivos .class, que foi solicitado.Muitas vezes, você pode estar vendo arquivos jar inteiros ou arquivos war que contêm muitos arquivos jar além deles mesmos.
Como não queria verificar manualmente cada classe, escrevi um programa java para fazer isso:
https://github.com/Nthalk/WhatJDK
Embora isso não diga com o que a classe foi compilada, ela determina com que JDKs serão capazes de CARREGAR as classes, o que provavelmente é o que você deseja começar.
fonte
Para expandir as respostas de Jonathon Faust e McDowell : Se você usa
od
um sistema baseado em * nix, pode usar (um dos primeiros programas Unix 1, que deve estar disponível em praticamente qualquer lugar) para consultar o.class
arquivo em nível binário:Esta saída vontade os valores inteiros conhecidos, por exemplo,
50
paraJava 5
,51
porJava 6
e assim por diante.1 Citação de https://en.wikipedia.org/wiki/Od_(Unix)
fonte
javac
versão que compilou os arquivos .class, que foi solicitado.Também escrevi meu próprio script bash para despejar a versão Java exigida por todos os frascos passados na linha de comando ... O meu é um pouco difícil, mas funciona para mim ;-)
exemplo de uso
jar_dump_version_of_jvm_required.sh
fonte
Você pode fazer isso facilmente na linha de comando usando o seguinte processo:
Se você conhece algum nome de classe no jar, pode usar o seguinte comando:
exemplo:
Resultado :
Referência rápida :
fonte
Você faz check-in no arquivo Manifest do exemplo do jar:
Versão do manifesto: 1.0 Criado por: 1.6.0 (IBM Corporation)
fonte
No Windows, faça o seguinte:
Agora, o Eclipse mostrará a versão principal e secundária exata.
fonte
Eu construo um pequeno script bash (no github) com base na sugestão de Davids usando o
file
comandofonte