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

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

Ответы [ 19 ]

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

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

Существует множество компиляторов, которые могут генерировать байт-код на каждом уровне, javac использует опцию «-target», чтобы указать, какой уровень байт-кода генерировать, а Java 6 javac может генерировать байт-код как минимум для 1.4, 1.5 и 6. Я не верю, что компилятор вставляет что-либо, что может идентифицировать сам компилятор, о чем я думаю, вы просите. Кроме того, все чаще используется компилятор Eclipse, так как это единственный jar, который может работать только с JRE.

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

2 голосов
/ 10 января 2015

Разработчики и администраторы, использующие 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 не имеет ничего полезного в манифесте относительно содержащихся классов.

1 голос
/ 14 апреля 2014

После ответа @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'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
1 голос
/ 21 июля 2017

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

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

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

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

1 голос
/ 29 марта 2016

В большинстве случаев вы можете просматривать целые jar-файлы или war-файлы, которые содержат много 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

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

0 голосов
/ 03 апреля 2019

Я также написал свой собственный скрипт bash для вывода версии Java, требуемой для всех jar-файлов, передаваемых в командной строке ... У меня немного грубовато, но у меня работает; -)

пример использования

$ jar_dump_version_of_jvm_required.sh *.jar
JVM VERSION REQUIRED: 46.0, /private/tmp/jars/WEB-INF/lib/json-simple-1.1.jar
JVM VERSION REQUIRED: 49.0, /private/tmp/jars/WEB-INF/lib/json-smart-1.1.1.jar
JVM VERSION REQUIRED: 50.0, /private/tmp/jars/WEB-INF/lib/jsontoken-1.0.jar
JVM VERSION REQUIRED: 50.0, /private/tmp/jars/WEB-INF/lib/jsr166y-1.7.0.jar

jar_dump_version_of_jvm_required.sh

#!/bin/bash

DIR=$(PWD)
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF

  Dumps the version of the JVM required to run the classes in a jar file

  usage: $ME JAR_FILE

  e.g. 

  $ME myFile.jar    ->  VERSION: 50.0     myFile.jar

  Java versions are:
  54 = Java 10
  53 = Java 9
  52 = Java 8
  51 = Java 7
  50 = Java 6
  49 = Java 5
  48 = Java 1.4
  47 = Java 1.3
  46 = Java 1.2
  45.3 = Java 1.1

EOF
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

function unzipJarToTmp()
{
  JAR=$1
  CLASS_FILE=$(jar -tf "$JAR" | grep \.class$ | grep -v '\$' | head -n1 | awk '{print $NF}')
  OUT_FILE="$CLASS_FILE"
  #echo "J=$JAR C=$CLASS_FILE O=$OUT_FILE"
  jar xf "$JAR" "$CLASS_FILE"

  MAJOR=$(javap -v "$OUT_FILE" 2>&1 | grep major | awk -F' ' '{print $3'})
  MINOR=$(javap -v "$OUT_FILE" 2>&1 | grep minor | awk -F' ' '{print $3'})
  if [ -z "$MAJOR" ]
  then
    echo "JVM VERSION REQUIRED: NA as no classes in $JAR"
  else
    echo "JVM VERSION REQUIRED: $MAJOR.$MINOR, $JAR"
  fi
}

# loop over cmd line args
for JAR in "$@"
do
  cd "$DIR"
  JAR_UID=$(basename "$JAR" | sed s/.jar//g)
  TMPDIR=/tmp/jar_dump/$JAR_UID/
  mkdir -p "$TMPDIR"
  JAR_ABS_PATH=$(realpath $JAR)

  cd "$TMPDIR"

  #echo "$JAR_ABS_PATH"
  unzipJarToTmp "$JAR_ABS_PATH"
  #sleep 2
done
0 голосов
/ 06 ноября 2014

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

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

Теперь Eclipse покажет точную главную и младшую версию.

0 голосов
/ 22 марта 2018

Вы проверяете в файле манифеста файла jar, например:

Версия манифеста: 1.0 Создано: 1.6.0 (IBM Corporation)

0 голосов
/ 20 февраля 2015

Я создаю небольшой скрипт bash (на github) на основе предложения Дэвидса, используя команду file

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