Какая версия javac построила мою банку?

Как я могу узнать, какая версия компилятора Java была использована для сборки банку? У меня есть файл jar, и он мог быть построен в любом из трех JDK. Нам нужно точно знать, какой из них, поэтому мы можем подтвердить совместимость. Является ли версия компилятора встроенной в файлы классов или jar?

Ответ 1

Вы не можете сказать из самого файла JAR, обязательно.

Загрузите шестнадцатеричный редактор и откройте один из файлов классов внутри JAR и посмотрите на байтовые смещения с 4 по 7. Введена информация о версии.

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

Примечание. Как упоминалось в комментарии ниже,

эти байты говорят вам, какую версию класс компилировали FOR, а не какая версия скомпилировала его.

Ответ 2

A jar является просто контейнером. Это файловый архив á la tar. Хотя jar может содержать интересную информацию в иерархии META-INF, она не обязана указывать урожайность классов внутри нее. Для этого нужно изучить файлы class.

Как как Питер Лоури, упомянутый в комментарии к исходному вопросу, вы не можете знать, какой выпуск JDK создал данный файл class, но вы можете найти из версии класса байтового кода файла class, содержащегося в jar.

Да, этот вид отстой, но первым шагом является извлечение одного или нескольких классов из jar. Например:

$ jar xf log4j-1.2.15.jar

В Linux, Mac OS X или Windows с установленной Cygwin file (1) знает версию класса.

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

Или, альтернативно, используя javap из JDK как @jikes.thunderbolt метко указывает:

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

И если вы отнесены к среде Windows без file или grep

> javap -v ./org/apache/log4j/Appender.class | findstr major
 major version: 45

FWIW, я соглашусь, что javap расскажет намного больше о данном файле class, чем заданный исходный вопрос.

В любом случае, другая версия класса, например:

$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0

Основное число версии класса соответствует следующим версиям 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

Ответ 3

Вот способ Java найти эту информацию.

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

Например:
> javap -v Application | findstr major   major version: 51

Ответ 4

Компилятор Java (javac) не создает jars, он переводит файлы Java в файлы классов. Инструмент Jar (jar) создает банки. Если пользовательский манифест не был указан, манифест по умолчанию укажет, какая версия JDK была использована для создания баннера.

Ответ 6

Код отправленный Owen, может сообщить вам информацию, указанную рядом других ответов здесь:

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
    }
}

См. также this и этот сайт. Я быстро модифицировал код Mind Products, чтобы проверить, для чего были скомпилированы каждая из моих зависимостей.

Ответ 7

Один вкладыш (Linux)

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

Это печатает содержимое файла MANIFEST.MF в stdout (надеюсь, что в файле jar есть один файл:)

В зависимости от того, что построил ваш пакет, вы найдете версию JDK в Created-By или Build-Jdk.

Ответ 8

Нет необходимости распаковывать JAR (если одно из имен классов известно или просматривается, например, с использованием 7zip), поэтому в Windows будет достаточно:

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

Ответ 9

Разработчики и администраторы, работающие под управлением Bash, могут найти полезные функции:

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."
}

Вы можете вставить их для одноразового использования или добавить их в ~/.bash_aliases или ~/.bashrc. Результаты выглядят примерно так:

$ jar_jdk_version poi-ooxml-3.5-FINAL.jar
49

и

$ print_jar_jdk_version poi-ooxml-3.5-FINAL.jar
poi-ooxml-3.5-FINAL.jar contains classes compiled with JDK version 1.5.

ИЗМЕНИТЬ Как указывает jackrabbit, вы не можете на 100% полагаться на манифест, чтобы сообщить вам что-нибудь полезное. Если бы это было так, вы могли бы вытащить его в своей любимой оболочке UNIX с помощью 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

Этот .jar не имеет ничего полезного в манифесте об содержащихся классах.

Ответ 10

Каждый файл класса имеет номер версии, встроенный для уровня байтового кода, который JVM использует, чтобы увидеть, нравится ли ему этот фрагмент байтового кода или нет. Это 48 для Java 1.4, 49 для Java 1.5 и 50 для Java 6.

Существует много компиляторов, которые могут генерировать байтовый код на каждом уровне, javac использует параметр "-target", чтобы указать, какой уровень байтового кода для генерации, а Java 6 javac может генерировать байтовый код как минимум для 1,4, 1,5 и 6. Я не считаю, что компилятор вставляет все, что может идентифицировать сам компилятор, о чем я думаю, что вы просите. Также все чаще используется компилятор Eclipse, поскольку он представляет собой единую банку, которая может работать только с JRE.

В файле jar обычно имеется много классов, и каждый из них независим, поэтому вам нужно исследовать все классы в банке, чтобы быть уверенными в характеристиках содержимого.

Ответ 11

В ответ на ответ @David J. Liszewski я выполнил следующие команды, чтобы извлечь манифест файла jar на 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 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

Ответ 12

Чтобы перейти на ответы Джонатона Фауста и McDowell: если вы используете систему на основе nix, вы можете использовать od (одну из первых программ Unix 1 которая должна быть доступна практически везде), чтобы запросить файл .class на двоичном уровне:

od -An -j7 -N1 -t dC SomeClassFile.class

Это приведет к получению знакомых целочисленных значений, например. 50 для Java 5, 51 для Java 6 и т.д.

1 Цитата из https://en.wikipedia.org/wiki/Od_(Unix)

Ответ 13

В Windows выполните следующие действия:

  • Разархивируйте или извлеките JAR файл с помощью команды WinZip/Java JAR.
  • Перетащите один из файлов классов в проект Java Eclipse.
  • Откройте файл класса.

Теперь Eclipse покажет точную основную и второстепенную версию.

Ответ 14

Я построю немного bash script (на github) на основе предложения Давидса с помощью команды file

Ответ 15

Много раз, вы могли бы смотреть на все файлы jar или военные файлы, которые содержат много файлов jar в дополнение к себе.

Поскольку я не хотел проверять каждый класс, я написал программу java для этого:

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

Пока это не говорит, что класс был скомпилирован WITH, он определяет, что JDK сможет ЗАГРУЗИТЬ классы, что, вероятно, вы хотели начать.