什么版本的javac构建了我的jar?

Ron*_*ero 200 java jar

如何判断使用哪个版本的Java编译器构建jar?我有一个jar文件,它可以在三个JDK中的任何一个中构建.我们需要确切地知道哪一个,所以我们可以证明兼容性.编译器版本是嵌入在类文件或jar中的某个位置吗?

Dav*_*ski 300

A jar只是一个容器.它是一个文件存档āla tar.虽然jar可能在其META-INF层次结构中包含有趣的信息,但它没有义务在其内容中指定类的复古.为此,必须检查class其中的文件.

正如Peter Lawrey在对原始问题的评论中提到的那样,您不一定知道哪个JDK版本构建了给定class文件,但您可以找到class包含在其中的文件的字节码类版本jar.

是的,这有点糟糕,但第一步是从中提取一个或多个类jar.例如:

$ jar xf log4j-1.2.15.jar
Run Code Online (Sandbox Code Playgroud)

在安装了Cygwin的 Linux,Mac OS X或Windows上,file(1)命令知道类版本.

$ file ./org/apache/log4j/Appender.class
./org/apache/log4j/Appender.class: compiled Java class data, version 45.3
Run Code Online (Sandbox Code Playgroud)

或者,使用javapJDK作为@jikes.thunderbolt恰当地指出:

$ javap -v ./org/apache/log4j/Appender.class | grep major
 major version: 45
Run Code Online (Sandbox Code Playgroud)

如果你被降级到Windows没有任何一个file或没有的环境grep

> javap -v ./org/apache/log4j/Appender.class | findstr major
 major version: 45
Run Code Online (Sandbox Code Playgroud)

FWIW,我会同意,这将比原始问题javap更能说明给定class文件.

无论如何,一个不同的类版本,例如:

$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0
Run Code Online (Sandbox Code Playgroud)

类版本主编号对应于以下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

  • 我的`file`版本没有显示,但我可以用这个命令手动检查类:`hexdump~/bin/classes/P.class | head`.只需查看第八个字节并转换为十进制. (7认同)
  • @JarettMillard我的cygwin`文件file.class`(5.22-1)最初没有显示java类目标:"file.class:[architecture = 6909806] [architecture = 6845039]".但是`file -k file.class`做到了:"file.class:[architecture = 6909806] [architecture = 6845039]编译的Java类数据,版本50.0(Java 1.6)".看起来`file`在没有`-k`的魔法文件数据库中只获得了第一个匹配. (3认同)
  • 使用“javap -p <class> | grep Major”并不可靠。如果 pom.xml 的源/目标为 1.7,则无论您使用 JDK 1.7、JDK 1.8 还是 JDK 1.9 进行编译,javap 都会始终为您提供“主要版本:51”。 (3认同)
  • FYI'文件'似乎依赖于Java版本是否也将显示JDK版本.在CentOS/Oracle Linux和Java 6编译的类中,我获得了"编译的Java类数据,版本50.0(Java 1.6)"但是当我在使用Java 7编译的类上运行它时,我只获得通用版本"编译的Java类数据,版本51.0" (2认同)
  • ``JAR=something.jar; 解压缩 -p $JAR `解压缩 -l $JAR | grep '\.class$' | grep '\.class$' | 头-1` | 文件-`` (2认同)

Jon*_*ust 85

你无法从JAR文件中分辨出来.

下载十六进制编辑器并打开JAR中的一个类文件,查看字节偏移4到7.版本信息是内置的.

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

注意:如下面的评论所述,

这些字节告诉你该类编译的版本是什么,而不是编译它的版本.

  • 为了迂腐,这些字节告诉你编译FOR的类的版本,而不是编译它的版本.Java允许您编译代码,以便它们与早期版本的Java兼容.但是,这仅适用于字节代码和格式.例如,它将很乐意编译将JDK 6库引用为JDK 5格式的代码.JDK 5将加载该类,但无法运行它,因为JDK 5库没有从JDK 6引用的代码. (39认同)
  • **[其他答案](http://stackoverflow.com/a/3313839/641451)告诉如何通过命令行轻松检查** (8认同)
  • 我们可以在清单文件中找到它创建者:1.7.0_21-b11(Oracle Corporation) (5认同)

小智 52

以下是Java查找此信息的方法.

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

例如:
> javap -v Application | findstr major   major version: 51

  • 在给出的所有答案中,您的答案是最简洁的,并且不涉及编写10行代码来了解版本信息.为此+1 (3认同)
  • `&lt;class&gt;` 参数有什么用? (2认同)

jac*_*bit 12

Java compiler(javac)不构建jar,它将Java文件转换为类文件.Jar工具(jar)创建实际的jar.如果未指定自定义清单,则默认清单将指定用于创建jar的JDK版本.

  • 虽然是真的,但这并没有提供问题的答案. (3认同)
  • @ zb226 AFAIK用于编译类的编译器版本无法从类文件中获取,只有类编译的版本为_for_.我提供的信息提供了唯一的(标准)信息,可用于建立人工制品的版本.如果那不是被问到的问题,那么问题应该改写. (2认同)

anr*_*nre 12

没有必要解压缩JAR(如果其中一个类名已知或被查找,例如使用7zip),那么在Windows上就足够了:

javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
Run Code Online (Sandbox Code Playgroud)

  • 这也适用于 Linux(当然,除了你使用 grep 而不是 findstr) (2认同)
  • 这些命令提供目标 JVM 版本,而不是编译 .class 文件的“javac”版本,这正是所要求的。 (2认同)

Wol*_*ahl 8

由于我需要分析胖罐子,因此我对jar文件中每个类的版本感兴趣。因此,我采用了Joe Liversedge的方法 /sf/answers/1951405081/并将其与David J. Liszewski的/sf/answers/231968761/类编号版本表结合起来以创建bash脚本jarv在jar文件中显示所有类文件的版本。

用法

usage: ./jarv jarfile
 -h|--help: show this usage
Run Code Online (Sandbox Code Playgroud)

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
...
Run Code Online (Sandbox Code Playgroud)

Bash脚本jarv

#!/bin/bash
# WF 2018-07-12
# find out the class versions with in jar file
# see /sf/ask/231947271/

# 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 
Run Code Online (Sandbox Code Playgroud)


cah*_*yaz 6

您可以使用十六进制编辑器从.class文件中找到Java编译器版本。

步骤1:使用zip提取程序从jar文件中提取.class文件

步骤2:使用十六进制编辑器打开.class文件。(我使用过notepad ++十六进制编辑器插件。此插件将文件读取为二进制文件,并以十六进制显示)。 在此处输入图片说明

索引6和7给出了所使用的类文件格式的主要版本号。 https://zh.wikipedia.org/wiki/Java_class_file

Java SE 11 = 55(十六进制0x37)

Java SE 10 = 54(十六进制0x36)

Java SE 9 = 53(十六进制0x35)

Java SE 8 = 52(十六进制0x34),

Java SE 7 = 51(16x 0x33),

Java SE 6.0 = 50(16x 0x32),

Java SE 5.0 = 49(十六进制0x31),

JDK 1.4 = 48(十六进制0x30),

JDK 1.3 = 47(十六进制0x2F),

JDK 1.2 = 46(十六进制0x2E),

JDK 1.1 = 45(十六进制0x2D)。


小智 5

一行 (Linux)

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

这会将文件的内容打印MANIFEST.MF到标准输出(希望您的 jar 文件中有一个:)

根据构建包的内容,您将在Created-ByBuild-Jdk键中找到 JDK 版本。

  • 请注意,这些字段没有义务出现在“MANIFEST.MF”中,也没有义务保证这些值是正确的(是的,我曾经遇到过一个“.jar”,其中的值是伪造的) )。 (3认同)

Adi*_*lli 5

IntelliJ 用户

  • 安装插件存档浏览器
  • 在 Intellij 中打开 Jar。您只需从文件浏览器中拖放 jar 文件即可将 jar 添加到任何项目。

  • 浏览 jar 文件以找到类文件,IntelliJ 的反编译器应显示用于创建 jar 的 Java 版本。

IntelliJ 显示 java 版本