用javap查看编译版本

本文介绍了如何使用javap命令查看Java class文件的编译版本,并解释了minor和major版本号的含义及其与JDK版本之间的对应关系。同时,文中还提到了如何通过javac的-target参数来指定编译时的目标JVM版本。
我们可以用javap命令查看class文件的编译版本。

比如对Worke.class使用javap命令:javap -verbose Worker
我将看到Worker的反编译结果。其中前几行如下:

[color=olive]Compiled from "Worker.java"
public class com.teleca.robin.Worker extends java.lang.Thread
SourceFile: "Worker.java"

[b] minor version: 0
major version: 49[/b]

Constant pool:[/color]
[color=olive]
上面的minor version: 0和major version: 49就是编译Worke.class时使用的jdk编译版本号。
[/color]

但是它并不是我们所熟悉的jdk版本号(比如jdk1.5)。
不过我们可以把从 JDK 1.1 到 JDK 1.7 编译器编译出的 class 的默认 minor.major version 汇总下就知道对应关系了。
[img]http://dl.iteye.com/upload/picture/pic/127293/39ae2b75-aac8-3a5c-a0bc-e9aa7030b3c4.png[/img]


[b]注1:javac 有个 -target 参数,编译时可以通过target参数来设置编译时所使用的jdk版本。比如如果目标 JVM 是 1.3 的话,编译选项就可以用 -target 1.3 -source 1.3 了。[/b]
相应的如果使用 ant ,编译时可以通过target参数来设置编译时所使用的jdk版本。比如:
<javac target="1.4" source="1.4" ............................/>

[b]注2:javac中source和target 的意义[/b]
-source <版本> 提供与指定版本的源兼容性
-target <版本> 生成特定 VM 版本的类文件
source才是真正的指明代码的兼容性,target则是指定了生成class的格式的版本号,即生成特定 VM 版本的类文件。


原文地址: [url]http://hubingforever.blog.163.com/blog/static/17104057920113262528403[/url]
<think>我们正在寻找如何查看Java文件的编译JDK版本信息的方法。根据引用[1]和引用[2],我们可以通过查看文件中的主版本号(major version)来确定编译该类的JDK版本。引用[1]提供了不同Java版本对应的主版本号,而引用[2]则展示了一个Java程序,用于读取类文件并输出其主版本号和次版本号。 方法一:使用命令行工具(如Linux下的od命令) 步骤: 1. 使用od命令查看文件的前几个字节(主要是第7和第8个字节,因为前4个字节是魔数CAFEBABE,接着两个字节是次版本号,再两个字节是主版本号)。 2. 定位到类文件的第7个字节(跳过前6个字节),然后读取两个字节(即第7和第8字节)作为主版本号。 示例命令: ```bash # 查看文件的前16个字节(以十六进制显示) od -t x1 -j 0 -N 16 YourClass.class ``` 输出可能类似于: ``` 0000000 ca fe ba be 00 00 00 34 00 23 ... ``` 其中,第5-8个字节(每两个为一组)表示次版本号和主版本号(这里00 00是次版本号,00 34是主版本号,转换为十进制是52,对应Java 8)。 注意:由于版本号是大端存储,所以上面00 34就是主版本号,十六进制的0034转换为十进制是52。 方法二:使用Java程序读取类文件(如引用[2]所示) 我们可以编写一个简单的Java程序来读取类文件的主版本号和次版本号。 示例代码(修改自引用[2]): ```java import java.io.*; public class ClassVersionChecker { private static final int MAGIC = 0xCAFEBABE; public static void main(String[] args) { if (args.length != 1) { System.out.println("Usage: java ClassVersionChecker <class file>"); return; } try (DataInputStream dis = new DataInputStream(new FileInputStream(args[0]))) { int magic = dis.readInt(); if (magic != MAGIC) { System.out.println("Not a valid class file!"); return; } int minorVersion = dis.readUnsignedShort(); int majorVersion = dis.readUnsignedShort(); System.out.println("Class version: " + majorVersion + "." + minorVersion); System.out.println("Compiled with JDK: " + mapMajorVersionToJDK(majorVersion)); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static String mapMajorVersionToJDK(int majorVersion) { // 根据引用[1]的映射关系 if (majorVersion >= 46) { int jdkVersion = majorVersion - 44; // 例如52对应8(因为52-44=8) if (majorVersion >= 49) { // Java 5开始是49 // 从Java 5(49)开始,版本号与JDK版本的对应关系为:majorVersion - 44 return "Java " + (majorVersion - 44); } else { // 对于更早的版本,可以直接用映射表 // 这里我们根据引用[1]的映射关系 switch (majorVersion) { case 46: return "Java 1.2"; case 47: return "Java 1.3"; case 48: return "Java 1.4"; default: return "Unknown"; } } } else { return "Pre-Java 1.2"; } } } ``` 使用步骤: 1. 将上述代码保存为ClassVersionChecker.java。 2. 编译该程序:`javac ClassVersionChecker.java` 3. 运行程序并指定要检查的类文件:`java ClassVersionChecker YourClass.class` 方法三:使用javap工具(JDK自带) 实际上,JDK自带的javap工具也可以查看文件的版本信息,但通常我们用它来查看字节码。不过,通过它的输出也可以间接得到版本号。 命令: ```bash javap -verbose YourClass | grep "major version" ``` 在输出中,我们可以看到类似这样的行: ``` major version: 52 ``` 然后根据引用[1]的映射关系,52对应Java 8。 注意:这个方法需要知道如何解析主版本号对应的JDK版本。 总结: 以上三种方法都可以查看文件的编译JDK版本。其中,使用javap命令可能是最简便的,因为不需要额外的工具或编写程序。 下面我们提供主版本号与JDK版本的对应关系(部分): - 52: Java 8 - 51: Java 7 - 50: Java 6 - 49: Java 5 - 48: Java 1.4 - 47: Java 1.3 - 46: Java 1.2 更多的版本对应关系可参考引用[1]。 因此,用户可以根据需要选择其中一种方法。 相关问题: 1. 如何通过命令行快速查看文件编译版本? 2. 主版本号与JDK版本之间的对应关系是怎样的? 3. 如何在没有安装JDK的环境中查看文件编译版本? </think>### 查看 Java文件编译版本的方法 以下是三种常用的方法,可快速检测 `.class` 文件的编译 JDK 版本: --- #### 方法一:使用 `javap` 工具(推荐) ```bash javap -verbose YourClass.class | grep "major" ``` **输出示例**: ```bash major version: 52 # 对应 Java 8 major version: 61 # 对应 Java 17 ``` **原理**: 类文件头部的 `major version` 标识编译时使用的 JDK 主版本号[^1][^2]。 --- #### 方法二:十六进制查看器(无需 JDK) ```bash # Linux/Mac xxd -p -l 8 YourClass.class | head -c 16 # Windows PowerShell Format-Hex -Path YourClass.class -Count 8 ``` **输出解析**: ``` cafebabe 0000 0034 │ └─ 主版本号(十六进制) └─ 次版本号 ``` **版本对应**: - `0034` (十六进制) = 52 (十进制) → **Java 8** - `003d` (十六进制) = 61 (十进制) → **Java 17** (完整对照表见下文)[^1] --- #### 方法三:Java 程序解析(可编程实现) ```java import java.io.*; public class ClassVersionChecker { public static void main(String[] args) throws IOException { try (DataInputStream dis = new DataInputStream( new FileInputStream("YourClass.class"))) { int magic = dis.readInt(); if (magic != 0xCAFEBABE) { System.out.println("无效的类文件"); return; } int minor = dis.readUnsignedShort(); // 次版本号 int major = dis.readUnsignedShort(); // 主版本号 System.out.printf("编译版本: Java %d (主版本 %d)%n", major - 44, major); // 转换公式 } } } ``` **输出**: ``` 编译版本: Java 8 (主版本 52) ``` --- ### JDK 版本与主版本号对照表 | 主版本号 | JDK 版本 | 类文件标识 | |---------|----------|-----------| | 52 | Java 8 | `0x34` (0034) | | 53 | Java 9 | `0x35` (0035) | | 55 | Java 11 | `0x37` (0037) | | 61 | Java 17 | `0x3D` (003d) | | 62 | Java 18 | `0x3E` (003e) | > 计算公式: **JDK版本 = 主版本号 - 44**[^1] > (例如:61 - 44 = 17 ⇒ Java 17) --- ### 关键原理 1. **魔数标识**:所有合法类文件以 `0xCAFEBABE` 开头(4字节)[^2] 2. **版本结构**: ``` [0-3] 字节: CA FE BA BE (魔数) [4-5] 字节: 次版本号 (通常为00 00) [6-7] 字节: 主版本号 (关键标识) ``` 3. **版本映射**:Oracle 采用线性映射策略,主版本号 = JDK主版本 + 44[^1] > **提示**:生产环境建议使用 `javap` 命令,开发调试可用十六进制查看器快速验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值