什么版本的 javac 构建了我的 jar?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3313532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What version of javac built my jar?
提问by Ron Romero
How can I tell what version of the Java compiler was used to build a jar? I have a jar file, and it could have been built in any one of three JDKs. We need to know exactly which one, so we can certify compatibility. Is the compiler version embedded somewhere in the class files or jar?
我如何知道使用哪个版本的 Java 编译器来构建 jar?我有一个 jar 文件,它可以用三个 JDK 中的任何一个构建。我们需要确切地知道是哪一个,以便我们可以证明兼容性。编译器版本是否嵌入在类文件或 jar 中的某处?
采纳答案by Jonathon Faust
You can't tell from the JAR file itself, necessarily.
您无法从 JAR 文件本身中分辨出来,这是必然的。
Download a hex editor and open one of the class files inside the JAR and look at byte offsets 4 through 7. The version information is built in.
下载一个十六进制编辑器并打开 JAR 中的一个类文件并查看字节偏移量 4 到 7。版本信息是内置的。
http://en.wikipedia.org/wiki/Java_class_file
http://en.wikipedia.org/wiki/Java_class_file
Note: As mentioned in the comment below,
注意:正如下面的评论中提到的,
those bytes tell you what version the class has been compiled FOR, not what version compiled it.
这些字节告诉您该类已编译为哪个版本,而不是编译它的版本。
回答by McDowell
You can tell the Java binary version by inspecting the first 8 bytes(or using an appthat can).
您可以通过检查前 8 个字节(或使用可以执行的应用程序)来判断 Java 二进制版本。
The compiler itself doesn't, to the best of my knowledge, insert any identifying signature. I can't spot such a thing in the file VM spec class formatanyway.
据我所知,编译器本身不会插入任何识别签名。无论如何,我无法在文件VM 规范类格式中发现这样的事情。
回答by Hymanrabbit
The Java compiler (javac
) does not build jars, it translates Java files into class files. The Jar tool (jar
) creates the actual jars. If no custom manifest was specified, the default manifest will specify which version of the JDK was used to create the jar.
Java 编译器 ( javac
) 不构建 jar,而是将 Java 文件转换为类文件。Jar 工具 ( jar
) 创建实际的 jar。如果未指定自定义清单,则默认清单将指定用于创建 jar 的 JDK 版本。
回答by Thorbj?rn Ravn Andersen
Each class file has a version number embedded for the byte code level which the JVM use to see if it likes that particular byte code chunk or not. This is 48 for Java 1.4, 49 for Java 1.5 and 50 for Java 6.
每个类文件都有一个为字节码级别嵌入的版本号,JVM 使用它来查看它是否喜欢特定的字节码块。Java 1.4 为 48,Java 1.5 为 49,Java 6 为 50。
Many compilers exist which can generate byte code at each level, javac uses the "-target" option to indicate which byte code level to generate, and the Java 6 javac can generate byte code for at least 1.4, 1.5 and 6. I do not believe that the compiler inserts anything that can identify the compiler itself which is what I think you ask for. Also the Eclipse compiler is increasingly being used, as it is a single jar which can run with the JRE only.
有很多编译器可以在每个级别生成字节码,javac 使用“-target”选项来指示生成哪个字节码级别,Java 6 javac 至少可以生成 1.4、1.5 和 6 的字节码。我不相信编译器会插入任何可以识别编译器本身的东西,这正是我认为你所要求的。Eclipse 编译器也越来越多地被使用,因为它是一个只能与 JRE 一起运行的 jar。
In a jar file there is usually many classes, and each of them is independent, so you need to investigate all classes in the jar to be certain about the characteristics of the contents.
一个jar文件中通常有很多类,每个类都是独立的,所以需要对jar中的所有类进行调查,确定内容的特点。
回答by David J. Liszewski
A jar
is merely a container. It is a file archive ā la tar
. While a jar
may have interesting information contained within it's META-INFhierarchy, it has no obligation to specify the vintage of the classes within it's contents. For that, one must examine the class
files therein.
Ajar
只是一个容器。它是一个档案档案 ā la tar
。虽然 ajar
的META-INF层次结构中可能包含有趣的信息,但它没有义务在其内容中指定类的年份。为此,必须检查class
其中的文件。
As as Peter Lawreymentioned in comment to the original question, you can't necessarily know which JDK release built a given class
file, but you can find out the byte code class version of the class
file contained in a jar
.
由于如彼得Lawrey在评论中提及了原来的问题,你不一定知道的JDK版本构建一个给定的class
文件,但你可以找出的字节码类版本class
包含在文件中jar
。
Yes, this kinda sucks, but the first step is to extract one or more classes from the jar
. For example:
是的,这有点糟糕,但第一步是从jar
. 例如:
$ jar xf log4j-1.2.15.jar
On Linux, Mac OS X or Windows with Cygwininstalled, the file(1)command knows the class version.
在安装了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
Or alternatively, using javap
from the JDK as @jikes.thunderbolt aptly points out:
或者,使用javap
JDK 作为 @jikes.thunderbolt 恰当地指出:
$ javap -v ./org/apache/log4j/Appender.class | grep major
major version: 45
And if you are relegated to a Windows
environment without either file
or grep
如果你被降级到一个Windows
没有任何一个file
或grep
> javap -v ./org/apache/log4j/Appender.class | findstr major
major version: 45
FWIW, I will concur that javap
will tell a whole lot more about a given class
file than the original question asked.
FWIW,我同意这javap
会class
比原始问题更详细地说明给定文件。
Anyway, a different class version, for example:
无论如何,一个不同的类版本,例如:
$ file ~/bin/classes/P.class
/home/dave/bin/classes/P.class: compiled Java class data, version 50.0
The class version major number corresponds to the following Java JDK versions:
类版本主编号对应于以下 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
- 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 = 爪哇 9
回答by JasonPlutext
The code posted by Owencan tell you the information mentioned by a number of the other answers here:
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
}
}
See also thisand thissite. I ended up modifying the Mind Products code quickly to check what each of my dependencies was compiled for.
回答by Alan
Following up on @David J. Liszewski's answer, I ran the following commands to extract the jar file's manifest on Ubuntu:
跟进@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
回答by Kittu
On Windows do the following:
在 Windows 上执行以下操作:
- Unzip or extract the JAR file using WinZip / Java JAR command.
- Drag and Drop one of the class files into your Eclipse Java project.
- Open the class file.
- 使用 WinZip / Java JAR 命令解压缩或提取 JAR 文件。
- 将类文件之一拖放到 Eclipse Java 项目中。
- 打开类文件。
Now Eclipse will show the exact major and minor version.
现在 Eclipse 将显示准确的主要和次要版本。
回答by jikes.thunderbolt
Here is Java's way to find this information.
这是 Java 查找此信息的方法。
Windows: javap -v <class> | findstr major
Unix: javap -v <class> | grep major
视窗:javap -v <class> | findstr major
Unix:javap -v <class> | grep major
For example:> javap -v Application | findstr major
major version: 51
例如:> javap -v Application | findstr major
major version: 51
回答by Joe Liversedge
Developers and administrators running Bash may find these convenience functions helpful:
运行 Bash 的开发人员和管理员可能会发现这些便利功能很有帮助:
jar_jdk_version() {
[[ -n "" && -x "`command -v javap`" ]] && javap -classpath "" -verbose $(jar -tf "" | 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 "")
case $version in 49) version=1.5;; 50) version=1.6;; 51) version=1.7;; 52) version=1.8;; esac
[[ -n "$version" ]] && echo "`basename ""` contains classes compiled with JDK version $version."
}
You can paste them in for one-time usage or add them to ~/.bash_aliases
or ~/.bashrc
. The results look something like:
您可以将它们粘贴到一次性使用或将它们添加到~/.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.
EDITAs Hymanrabbitpoints out, you can't 100% rely on the manifest to tell you anything useful. If it was, then you could pull it out in your favorite UNIX shell with unzip
:
编辑正如Hymanrabbit指出的那样,您不能 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
This .jar doesn't have anything useful in the manifest about the contained classes.
这个 .jar 在关于所包含类的清单中没有任何有用的东西。