我如何知道哪个版本的Java编译器被用来构建一个jar?我有一个jar文件,它可以构建在三个jdk中的任何一个中。我们需要确切知道是哪一个,这样我们才能证明兼容性。编译器版本是否嵌入到类文件或jar中?
当前回答
一行程序(Linux)
解压-p mylib.jar META-INF/MANIFEST. jar曼氏金融
这将打印MANIFEST的内容。MF文件转换为stdout(希望你的jar文件中有一个:)
根据构建包的方式,您将在“Created-By”或“Build-Jdk”键中找到JDK版本。
其他回答
罐子只是一个容器。它是一个文件归档文件(ā 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
IntelliJ Users
安装插件Archive Browser
在Intellij中打开罐子通过从文件浏览器中拖拽jar文件,您可以简单地将jar添加到任何项目中。 浏览jar文件以找到一个类文件,IntelliJ的反编译器应该显示用于创建jar的Java版本。
每个类文件都嵌入了字节代码级别的版本号,JVM使用该版本号来查看它是否喜欢特定的字节代码块。Java 1.4是48,Java 1.5是49,Java 6是50。
有许多编译器可以在每个级别生成字节代码,javac使用“-target”选项来指示要生成哪个字节代码级别,Java 6 javac可以生成至少1.4、1.5和6级的字节代码。我不相信编译器插入任何可以识别编译器本身,这是我认为你要求的。Eclipse编译器也越来越多地被使用,因为它是一个单独的jar,只能与JRE一起运行。
在jar文件中通常有许多类,并且每个类都是独立的,因此您需要研究jar中的所有类,以确定内容的特征。
根据@David J. Liszewski的回答,我运行以下命令在Ubuntu上提取jar文件的清单:
# Determine the manifest file name:
$ jar tf LuceneSearch.jar | grep -i manifest
META-INF/MANIFEST.MF
# Extract the file:
$ sudo jar xf LuceneSearch.jar META-INF/MANIFEST.MF
# Print the file's contents:
$ more META-INF/MANIFEST.MF
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b30 (Oracle Corporation)
Main-Class: org.wikimedia.lsearch.config.StartupManager
Owen发布的代码可以告诉你一些其他答案中提到的信息:
public void simpleExample ()
{
FileInputStream fis = new FileInputStream ("mytest.class");
parseJavaClassFile ( fis );
}
protected void parseJavaClassFile ( InputStream classByteStream ) throws Exception
{
DataInputStream dataInputStream = new DataInputStream ( classByteStream );
magicNumber = dataInputStream.readInt();
if ( magicNumber == 0xCAFEBABE )
{
int minorVer = dataInputStream.readUnsignedShort();
int majorVer = dataInputStream.readUnsignedShort();
// do something here with major & minor numbers
}
}
也可以看看这个和这个网站。最后,我迅速修改了Mind Products代码,以检查我的每个依赖项是为了什么而编译的。
推荐文章
- 如何添加JTable在JPanel与空布局?
- Statement和PreparedStatement的区别
- 为什么不能在Java中扩展注释?
- 在Java中使用UUID的最重要位的碰撞可能性
- 转换列表的最佳方法:map还是foreach?
- 如何分割逗号分隔的字符串?
- 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的区别是什么?