我如何知道哪个版本的Java编译器被用来构建一个jar?我有一个jar文件,它可以构建在三个jdk中的任何一个中。我们需要确切知道是哪一个,这样我们才能证明兼容性。编译器版本是否嵌入到类文件或jar中?
当前回答
一行程序(Linux)
解压-p mylib.jar META-INF/MANIFEST. jar曼氏金融
这将打印MANIFEST的内容。MF文件转换为stdout(希望你的jar文件中有一个:)
根据构建包的方式,您将在“Created-By”或“Build-Jdk”键中找到JDK版本。
其他回答
我基于david的建议使用file命令构建了一个小bash脚本(在github上)
您不一定能从JAR文件本身判断出来。
下载一个十六进制编辑器,打开JAR中的一个类文件,查看字节偏移量4到7。版本信息是内置的。
http://en.wikipedia.org/wiki/Java_class_file
注:如以下评论所述,
这些字节告诉你类是为哪个版本编译的,而不是 哪个版本编译了它。
在Windows上执行以下操作:
使用WinZip / Java JAR命令解压或解压缩JAR文件。 将其中一个类文件拖放到Eclipse Java项目中。 打开类文件。
现在Eclipse将显示准确的主版本和次版本。
因为我需要分析fat jar,所以我对jar文件中每个单独类的版本感兴趣。因此我采取了乔·利弗塞奇的方法 https://stackoverflow.com/a/27877215/1497139,并将其与David J. Liszewski的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 https://stackoverflow.com/questions/3313532/what-version-of-javac-built-my-jar
# 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
我也写了自己的bash脚本来转储所有在命令行传递的jar所需的Java版本…我的有点粗糙,但适合我;-)
示例使用
$ 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
推荐文章
- Intellij IDEA Java类在保存时不能自动编译
- 何时使用Mockito.verify()?
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式
- 如何从线程捕获异常
- 无法解析主机"<URL here>"没有与主机名关联的地址
- 如何在Java中打印二叉树图?
- String.format()在Java中格式化双重格式
- com.jcraft.jsch.JSchException: UnknownHostKey
- Java中的操作符重载
- 如何加速gwt编译器?
- 在Hibernate中重新连接分离对象的正确方法是什么?
- 应该……接住环内还是环外?