你们中没有人知道将搜索.class文件然后显示其编译版本的工具吗?
我知道您可以在十六进制编辑器中单独查看它们,但是我要查看很多类文件(由于某种原因,我的大型应用程序中的某些内容正在编译为Java6)。
使用JDK随附的javap工具。 -verbose选项将打印类文件的版本号。
1 2 3 4 5 6 7
| > javap -verbose MyClass
Compiled from"MyClass.java"
public class MyClass
SourceFile:"MyClass.java"
minor version: 0
major version: 46
... |
仅显示版本:
1 2
| WINDOWS> javap -verbose MyClass | find"version"
LINUX > javap -verbose MyClass | grep version |
无需第三方API即可轻松读取类文件签名并获取这些值。您需要做的就是读取前8个字节。
1 2 3 4
| ClassFile {
u4 magic;
u2 minor_version;
u2 major_version; |
对于51.0版的类文件(Java 7),起始字节为:
...其中0xCAFEBABE是魔术字节,0x0000是次要版本,0x0033是主要版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import java.io.*;
public class Demo {
public static void main(String[] args) throws IOException {
ClassLoader loader = Demo.class.getClassLoader();
try (InputStream in = loader.getResourceAsStream("Demo.class");
DataInputStream data = new DataInputStream(in)) {
if (0xCAFEBABE != data.readInt()) {
throw new IOException("invalid header");
}
int minor = data.readUnsignedShort();
int major = data.readUnsignedShort();
System.out.println(major +"." + minor);
}
}
} |
遍历目录(文件)和档案(JarFile)查找类文件是微不足道的。
Oracle的Joe Darcy的博客列出了从Java到Java 7的类版本到JDK版本的映射:
1 2 3 4 5 6 7 8 9 10
| Target Major.minor Hex
1.1 45.3 0x2D
1.2 46.0 0x2E
1.3 47.0 0x2F
1.4 48.0 0x30
5 (1.5) 49.0 0x31
6 (1.6) 50.0 0x32
7 (1.7) 51.0 0x33
8 (1.8) 52.0 0x34
9 53.0 0x35 |
在类Unix上
1
| file /path/to/Thing.class |
还将提供文件类型和版本。输出如下所示:
compiled Java class data, version 49.0
如果您使用的是Unix系统,则可以执行
1
| find /target-folder -name \*.class | xargs file | grep"version 50\.0" |
(我的文件版本对Java6类说"编译的Java类数据,版本50.0")。
另一个Java版本检查
1
| od -t d -j 7 -N 1 ApplicationContextProvider.class | head -1 | awk '{print"Java", $2 - 44}' |
在月食中,如果您没有附加源。注意附加源按钮后的第一行。
//从CDestinoLog.java编译(版本1.5:49.0,超级位)
也许这也对某人有帮助。看起来有一种更简单的方法来获取用于编译/构建.class的JAVA版本。这种方式对于JAVA版本的应用程序/类自检很有用。
我遍历了JDK库,发现了这个有用的常量:
com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION。
我不知道它何时在JAVA JDK中。
尝试使用这段代码获取多个版本常量,结果如下:
src:
1 2 3 4 5
| System.out.println("JAVA DEV ver.:" + com.sun.deploy.config.BuiltInProperties.CURRENT_VERSION);
System.out.println("JAVA RUN v. X.Y:" + System.getProperty("java.specification.version") );
System.out.println("JAVA RUN v. W.X.Y.Z:" + com.sun.deploy.config.Config.getJavaVersion() ); //_javaVersionProperty
System.out.println("JAVA RUN full ver.:" + System.getProperty("java.runtime.version") +" (may return unknown)" );
System.out.println("JAVA RUN type:" + com.sun.deploy.config.Config.getJavaRuntimeNameProperty() ); |
输出:
1 2 3 4 5
| JAVA DEV ver.: 1.8.0_77
JAVA RUN v. X.Y: 1.8
JAVA RUN v. W.X.Y.Z: 1.8.0_91
JAVA RUN full ver.: 1.8.0_91-b14 (may return unknown)
JAVA RUN type: Java(TM) SE Runtime Environment |
在类字节码中确实存储有常量-请参见Main.call中红色标记的部分-存储在.class字节码中的常量
常量在类中,用于检查JAVA版本是否已过期(请参阅Java如何检查已过期)...