从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • RSS
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金等
  • 职场规划
  • 关于离职
  • 杂谈
  • 📖 读书

    • 读书工具
    • 读书笔记
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

    • 我的 Java 学习路线
    • 安装 Java
    • Java数据类型

    • Java 多版本配置
    • 面向对象

      • 枚举类
      • static 关键字
      • classpath:JVM 查找类的机制
      • 包:Java 组织类的方式
      • jar 包
      • class 版本
        • 前言
        • 用 Java11 编写和运行代码
        • 用 Java8 运行 Java11 的代码
        • 查看 Java8 的 class 文件版本
        • 尝试用 Java11 运行 Java8 的 class
        • 指定编译出来的 class 文件版本
        • 小结
        • 参考
      • 抽象类
      • 接口
      • 访问性修饰符
      • 非访问性修饰符
      • 内部类
    • Java核心类

    • IO

    • Java与时间

    • 异常处理

    • 哈希和加密算法

    • Java8新特性

    • 网络编程

  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java
  • JavaSE
  • 面向对象
2022-11-27
目录

class 版本

# class 版本

不同 JDK 版本生成的 class 文件版本也不同,这就涉及到版本问题。

# 前言

Java 有很多个版本,我们通常说的 Java 8,Java 11,Java 17,是指 JDK 的版本,也就是 JVM 的版本,更确切地说,就是 java.exe 这个程序的版本:

> java -version
java version "1.8.0_351"
1
2

class 文件也有对应版本。例如,Java8 对应的 class 文件版本是 52, Java 11 是 55,而 Java 17 是 61。

目前用的最广泛的是 Java8,这就涉及到一些版本的问题:

  • 那如果后续升级了 JDK 版本,还能运行之前用低版本的 Java 编译后的 class 文件吗?可以的;
  • 如果后续降级了 JDK 版本,还能运行高版本的 Java 编译后的 class 文件吗?不可以,需要重新编译。

这里引用廖雪峰老师的比喻:

打个比方,用 Word 2013 保存一个 Word 文件,这个文件也可以在 Word 2016 上打开。但反过来,用 Word 2016 保存一个 Word 文件,就无法使用 Word 2013 打开。

但是,且慢,用 Word 2016 也可以保存一个格式为 Word 2013 的文件,这样保存的 Word 文件就可以用低版本的 Word 2013 打开,但前提是保存时必须明确指定文件格式兼容 Word 2013。

接下来我们可以实践一下,同时一个高版本的 Java(为了方便后续的学习,我们还会讲如何切换回低版本),参考教程可以参考我写的另一篇博客:Java 多版本配置 (opens new window)

# 用 Java11 编写和运行代码

我们先切换到 Java11,新建和运行 Java 代码:

新建一个 Hello11.java 文件,代码如下

public class Hello11{
  public static void main(String[] args){
    System.out.println("Hello Java11 !");
  }
}
1
2
3
4
5
> javac Hello11.java
> java Hello11
Hello Java11 !
1
2
3

切换到 Java8 之前,我们先查看 class 版本:

D:\DownLoad>javap -v Hello11.class
Classfile /D:/DownLoad/Hello11.class
  Last modified 2022年11月27日; size 422 bytes
  MD5 checksum d35ca922fd955c1886c8c143c0a2ccea
  Compiled from "Hello11.java"
public class Hello11
  minor version: 0
  major version: 55
1
2
3
4
5
6
7
8

第 8 行就是 class 文件的版本:55. 后面还有更多关于该 class 文件的信息,这里不表。

# 用 Java8 运行 Java11 的代码

接下来,我们切换回 Java8,然后尝试运行:

D:\DownLoad>java Hello11
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Hello11 has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
1
2
3

可以看到有报错 UnsupportedClassVersionError,这个就是因为 class 版本不兼容的问题。

# 查看 Java8 的 class 文件版本

我们尝试用 Java8 重新编译,然后查看 class 文件版本

D:\DownLoad>javap -v Hello11.class
Classfile /D:/DownLoad/Hello11.class
  Last modified 2022-11-27; size 422 bytes
  MD5 checksum 08ed42a4993c6150bd3bcf66dd0873b3
  Compiled from "Hello11.java"
public class Hello11
  minor version: 0
  major version: 52
1
2
3
4
5
6
7
8

可以看到 class 文件的版本为 52

# 尝试用 Java11 运行 Java8 的 class

Java 版本大部分情况下都是向后兼容的,也就是高版本的 Java 能运行低版本的 class 文件。

我们试着运行,没有问题,Java 代码能正常执行:

D:\DownLoad>javap -v Hello11.class
Classfile /D:/DownLoad/Hello11.class
  Last modified 2022年11月27日; size 422 bytes
  MD5 checksum 08ed42a4993c6150bd3bcf66dd0873b3
  Compiled from "Hello11.java"
public class Hello11
  minor version: 0
  major version: 52


D:\DownLoad>java Hello11
Hello Java11 !
1
2
3
4
5
6
7
8
9
10
11
12

# 指定编译出来的 class 文件版本

我们可以让 Java11 编译出来的 class 文件兼容 Java8,只需在命令行里指定版本即可。

第一种方式:使用--release 选项

javac --release 8 Hello11.class
1

参数 --release 8 表示源码兼容 Java8

第二种方式:使用--source 和 --target 选项

javac --source 9 --target 11 Main.java
1

参数 --source 指定源码版本,参数 --target 指定输出 class 版本。

注意:

  1. 两种方式不能混用,例如又用--source,又用--release。
  2. 有些 Java11 的新特性(例如 String 类的新方法 indent),只能在 Java11 运行。即使指定了兼容 Java8,在 Java8 也运行不了。但如果使用--release 11 则会在编译时检查该方法是否在 Java 11 中存在。
  3. 如果使用 javac 编译时不指定任何版本参数,那么相当于使用 --release 当前版本 编译,即源码版本和输出版本均为当前版本。

# 小结

高版本的 JDK 可编译输出低版本兼容的 class 文件,但需注意,低版本的 JDK 可能不存在高版本 JDK 添加的类和方法,导致运行时报错。

运行时使用哪个 JDK 版本,编译时就尽量使用同一版本编译源码。

# 参考

本文主要参考了廖雪峰老师的博客:class 版本 - 廖雪峰的官方网站 (opens new window)

上次更新: 2024/9/30 20:09:39
jar 包
抽象类

← jar 包 抽象类→

最近更新
01
吐槽一下《僵尸校园》
05-15
02
2025 年 4 月记
04-30
03
山西大同 “订婚强奸案” 将会给整个社会带来的影响有多严重? - 知乎 转载
04-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式