如何判断使用哪个版本的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版本:
Jon*_*ust 85
你无法从JAR文件中分辨出来.
下载十六进制编辑器并打开JAR中的一个类文件,查看字节偏移4到7.版本信息是内置的.
http://en.wikipedia.org/wiki/Java_class_file
注意:如下面的评论所述,
这些字节告诉你该类编译的版本是什么,而不是编译它的版本.
小智 52
以下是Java查找此信息的方法.
Windows:javap -v <class> | findstr major
Unix:javap -v <class> | grep major
例如:
> javap -v Application | findstr major
major version: 51
jac*_*bit 12
Java compiler(javac)不构建jar,它将Java文件转换为类文件.Jar工具(jar)创建实际的jar.如果未指定自定义清单,则默认清单将指定用于创建jar的JDK版本.
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)
由于我需要分析胖罐子,因此我对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)
您可以使用十六进制编辑器从.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-By或Build-Jdk键中找到 JDK 版本。
在 Intellij 中打开 Jar。您只需从文件浏览器中拖放 jar 文件即可将 jar 添加到任何项目。
浏览 jar 文件以找到类文件,IntelliJ 的反编译器应显示用于创建 jar 的 Java 版本。
| 归档时间: |
|
| 查看次数: |
173854 次 |
| 最近记录: |