如何判断使用哪个版本的Java编译器构建jar?我有一个jar文件,它可以在三个JDK中的任何一个中构建.我们需要确切地知道哪一个,所以我们可以证明兼容性.编译器版本是嵌入在类文件或jar中的某个位置吗?
A jar
只是一个容器.它是一个文件存档āla tar
.虽然jar
可能在其META-INF层次结构中包含有趣的信息,但它没有义务在其内容中指定类的复古.为此,必须检查class
其中的文件.
正如Peter Lawrey在对原始问题的评论中提到的那样,您不一定知道哪个JDK版本构建了给定class
文件,但您可以找到class
包含在其中的文件的字节码类版本jar
.
是的,这有点糟糕,但第一步是从中提取一个或多个类jar
.例如:
$ jar xf log4j-1.2.15.jar
在安装了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
或者,使用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
你无法从JAR文件中分辨出来.
下载十六进制编辑器并打开JAR中的一个类文件,查看字节偏移4到7.版本信息是内置的.
http://en.wikipedia.org/wiki/Java_class_file
注意:如下面的评论所述,
这些字节告诉你该类编译的版本是什么,而不是编译它的版本.
以下是Java查找此信息的方法.
Windows:javap -v
Unix:javap -v
例如:
> javap -v Application | findstr major
major version: 51
Java compiler(javac
)不构建jar,它将Java文件转换为类文件.Jar工具(jar
)创建实际的jar.如果未指定自定义清单,则默认清单将指定用于创建jar的JDK版本.
没有必要解压缩JAR(如果其中一个类名已知或被查找,例如使用7zip),那么在Windows上就足够了:
javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
由于我需要分析胖罐子,因此我对jar文件中每个类的版本感兴趣。因此,我采用了Joe Liversedge的方法 /sf/ask/17360801/并将其与David J. Liszewski的/sf/ask/17360801/类编号版本表结合起来以创建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 /sf/ask/17360801/ # 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
您可以使用十六进制编辑器从.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)。