从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

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

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

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

    • IO

    • Java与时间

    • 异常处理

    • 哈希和加密算法

    • Java8新特性

    • 网络编程

    • Java
  • JavaSenior

  • JavaEE

  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • 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(为了方便后续的学习,我们还会讲如何切换回低版本),更多参考https://www.peterjxl.com/Java/Java-install-multi-version

‍

# 用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)

在GitHub上编辑此页 (opens new window)
上次更新: 2023/1/23 17:06:18
jar包
抽象类

← jar包 抽象类→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式