Какая версия Javac построил мою банку? - PullRequest
194 голосов
/ 23 июля 2010

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

Ответы [ 19 ]

298 голосов
/ 23 июля 2010

A jar - это просто контейнер. Это файловый архив а-ля 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
85 голосов
/ 23 июля 2010

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

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

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

Примечание: как указано в комментарии ниже,

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

51 голосов
/ 20 ноября 2014

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

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

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

12 голосов
/ 23 июля 2010

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

11 голосов
/ 08 августа 2016

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

javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
7 голосов
/ 12 июля 2018

Поскольку мне нужно было анализировать толстые банки, меня интересовала версия каждого отдельного класса в файле jar.Поэтому я использовал подход Джо Ливерседжа https://stackoverflow.com/a/27877215/1497139 и соединил его с таблицей версий номера класса Дэвида Дж. Лизевского https://stackoverflow.com/a/3313839/1497139 для создания сценария bash jarv для отображения версий всех файлов классов в файле jar.

использование

usage: ./jarv jarfile
 -h|--help: show this usage

Пример

jarv $Home/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar

java 1.4 org.apache.log4j.Appender
java 1.4 org.apache.log4j.AppenderSkeleton
java 1.4 org.apache.log4j.AsyncAppender$DiscardSummary
java 1.4 org.apache.log4j.AsyncAppender$Dispatcher
...

Bash-скрипт jarv

#!/bin/bash
# WF 2018-07-12
# find out the class versions with in jar file
# see /2534707/kakaya-versiya-javac-postroil-moy-banku

# uncomment do debug
# set -x

#ansi colors
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
blue='\033[0;34m'  
red='\033[0;31m'  
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
endColor='\033[0m'

#
# a colored message 
#   params:
#     1: l_color - the color of the message
#     2: l_msg - the message to display
#
color_msg() {
  local l_color="$1"
  local l_msg="$2"
  echo -e "${l_color}$l_msg${endColor}"
}

#
# error
#
#   show an error message and exit
#
#   params:
#     1: l_msg - the message to display
error() {
  local l_msg="$1"
  # use ansi red for error
  color_msg $red "Error: $l_msg" 1>&2
  exit 1
}

#
# show the usage
#
usage() {
  echo "usage: $0 jarfile"
  # -h|--help|usage|show this usage
  echo " -h|--help: show this usage"
  exit 1 
}

#
# showclassversions
#
showclassversions() {
  local l_jar="$1"
  jar -tf "$l_jar" | grep '.class' | while read classname
  do
    class=$(echo $classname | sed -e 's/\.class$//')
    class_version=$(javap -classpath "$l_jar" -verbose $class | grep 'major version' | cut -f2 -d ":" | cut -c2-)
    class_pretty=$(echo $class | sed -e 's#/#.#g')
    case $class_version in
      45.3) java_version="java 1.1";;
      46) java_version="java 1.2";;
      47) java_version="java 1.3";;
      48) java_version="java 1.4";;
      49) java_version="java5";;
      50) java_version="java6";;
      51) java_version="java7";;
      52) java_version="java8";;
      53) java_version="java9";;
      54) java_version="java10";;
      *) java_version="x${class_version}x";;
    esac
    echo $java_version $class_pretty
  done
}

# check the number of parameters
if [ $# -lt 1 ]
then
  usage
fi

# start of script
# check arguments
while test $# -gt 0
do
  case $1 in
    # -h|--help|usage|show this usage
    -h|--help) 
      usage
      exit 1
      ;;
    *)
     showclassversions "$1"
  esac
  shift
done 
6 голосов
/ 08 августа 2018

Вы можете найти версию компилятора Java из файлов .class, используя Hex Editor.

Шаг 1: Извлечение файлов .class из файла jar с помощью zip extractor

шаг 2: откройте файл .class с помощью шестнадцатеричного редактора (я использовал плагин hexpad редактора notepad ++. Этот плагин читает файл как двоичный файл и показывает его в шестнадцатеричном формате) Вы можете увидеть ниже. enter image description here

Индексы 6 и 7 дают основной номер версии используемого файла класса. 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),

JDK 1,2 = 46 (гекс 0x2E),

JDK 1.1 = 45 (0x2D hex).

4 голосов
/ 23 июля 2010

Бинарную версию Java можно узнать, проверив первые 8 байтов (или используя приложение , которое может).

Насколько мне известно, сам компилятор не вставляет никакую идентификационную подпись. Я не могу обнаружить такую ​​вещь в файле Формат класса спецификации VM в любом случае.

4 голосов
/ 25 июня 2011

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

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

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

3 голосов
/ 14 августа 2015

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

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

Печатает содержимое файла MANIFEST.MF на стандартный вывод (возможно, в вашем файле jar есть такой):

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...