我如何知道哪个版本的Java编译器被用来构建一个jar?我有一个jar文件,它可以构建在三个jdk中的任何一个中。我们需要确切知道是哪一个,这样我们才能证明兼容性。编译器版本是否嵌入到类文件或jar中?
当前回答
为了扩展Jonathon Faust和McDowell的回答:如果你在一个基于*nix的系统上,你可以使用od(最早的Unix程序之一,应该在几乎所有地方都可以使用)在二进制级别上查询.class文件:
od -An -j7 -N1 -t dC SomeClassFile.class
这将输出熟悉的整数值,例如,Java 5输出50,Java 6输出51,等等。
1引用自https://en.wikipedia.org/wiki/Od_(Unix)
其他回答
基于现有的答案,我试图构建一些更方便的东西,应该在大多数操作系统上工作(这取决于cat, xxd和awk),你只需要把你的类文件名从你的jar中提取出来。
cat YOUR_FILE.class | xxd -s 7 -l1 | awk '{print $2}' | sed -e 's/34/Java SE 8/' -e 's/35/Java SE 9/' -e 's/36/Java SE 10/' -e 's/37/Java SE 11/' -e 's/38/Java SE 12/' -e 's/39/Java SE 13/' -e 's/3a/Java SE 14/' -e 's/3b/Java SE 15/' -e 's/3c/Java SE 16/' -e 's/3d/Java SE 17/' -e 's/3e/Java SE 18/'
方便的映射到人类可读的版本适用于Java 8开始的主要版本。(否则你会得到主版本的普通十六进制版本号,参见1中的链接。对于一个定义)
这个小脚本是基于什么:
我使用类文件的内容,并使用xxd获取第7个字节。 根据定义,这是用于主要版本的,参见维基百科: https://en.wikipedia.org/wiki/Java_class_file 然后我只是用一个列表代替所有版本值开始的十六进制34 java 8和结束的十六进制3e java 18。
IntelliJ Users
安装插件Archive Browser
在Intellij中打开罐子通过从文件浏览器中拖拽jar文件,您可以简单地将jar添加到任何项目中。 浏览jar文件以找到一个类文件,IntelliJ的反编译器应该显示用于创建jar的Java版本。
罐子只是一个容器。它是一个文件归档文件(ā la tar或zip)。虽然jar可能在其META-INF层次结构中包含有趣的信息,但它没有义务指定其内容中的类的年份。为此,必须检查其中的类文件。
正如Peter Lawrey在对原始问题的评论中提到的,您不一定知道哪个JDK版本构建了给定的类文件,但您可以找到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
或者,使用JDK中的javap作为@jikes。Thunderbolt恰当地指出:
$ javap -v ./org/apache/log4j/Appender.class | grep major
major version: 45
对于没有文件或grep的Windows环境
> javap -v ./org/apache/log4j/Appender.class | findstr major
major version: 45
FWIW,我同意javap会告诉一个给定的类文件比最初的问题更多的信息。
总之,一个不同的类版本,例如:
$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0
下面的列表显示了类版本的主版本号和引入类主版本的JDK版本。
注意:类版本不一定标识用于编译类的JDK -它只标识可能生成该类的最早版本。
例如,类主版本52可以由Java 7之后的任何JDK生成。
45.3 = Java 1.1 46 = Java 1.2 47 = Java 1.3 48 = java1.4 49 = Java 5 50 = Java 6 51 = Java 7 52 = Java 8 53 = Java 9 54 = Java 10 55 = Java 11 56 = Java 12 57 = Java 13 58 = Java 14 59 = Java 15 60 = Java 16 61 = Java 17 62 = Java 18 63 = Java 19
运行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
and
$ 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 shell中使用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在清单中没有任何关于所包含类的有用信息。
不需要解包JAR(如果其中一个类名已知或被查找,例如使用7zip),因此在Windows上,以下步骤就足够了:
javap -cp log4j-core-2.5.jar -verbose org.apache.logging.log4j.core.Logger | findstr major
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?