2023-03-19  阅读(1)
原文作者:简单教程 原文地址: https://www.twle.cn/c/yufei/java9/java9-basic-intro.html

Java 9 之前的 JAR 格式中只能包含一个 Java 版本,显然,这是不符合 Java 这种开启了版本帝的发展线路了,想想,现在大多数 Java 还停留在 Java 6 7 8 的年代,Java 10 已经发布,如果要发布一个 JAR 格式的类库,意味着要编译多个版本的 JAR, 6 7 8 9 10 五个版本,看起来也太恐怖了。

Java 9 突然间良心发现,开始支持多版本共存的 JAR 了。

Java 9 引入了一个新的功能,其实也不算吧,就是增强了 JAR 格式,可以在同一个 JAR 中维护和使用不同版本的 java 类或资源

JAR 多版本共存原理

首先在 JAR 中,文件 MANIFEST.MF 文件的 main 节中有一个条目 Multi-Release:true , 用于指定该 JAR 包是多 Java 版本共存的

同时,JAR 目录下的子目录 META-INF 还包含一个 versions 子目录,其子目录 ( 从 9 开始,用于 Java 9 ) 存储特定于版本的类和资源文件

多版本 JAR 范例

接下来这个范例,我们的多版本 JAR 中有三个版本的 MultiReleaseJarTester.java 文件,一个用于 JDK 8,一个用于 JDK 9,最后一个用于 JDK 10 并在可以在这些不同的 JDK 版本上运行

  1. 首先,我们在当前工作目录,例如我的是 d:\devops\java9 创建一个 multireleasejar 文件

    然后创建一个目录 src/main 目录,并在该目录中创建 java10 目录

    并在 java10 目录中创建 cn/twle

    创建完成后,目录结果如下

         .
        └── src
            └── main
                ├── java10
                    └── cn
                        └── twle
  1. 然后在 java10/cn/twle 目录下新建 MultiReleaseJarTester.java 文件并输入以下内容
        package cn.twle;
        
        public class MultiReleaseJarTester {
           public static void main(String[] args) {
        
                String javaVersion = System.getProperty("java.version");
                System.out.println("JDK version is:" + javaVersion);
           }
        }
创建完成后目录结构如下
        .
        └── src
            └── main
                ├── java10
                    └── cn
                        └── twle
                            └── MultiReleaseJarTester.java
  1. 然后重复 2-3 步骤,创建相同的目录 java9java8 ,内容都是一样的,创建完成后目录结构如下
        .
        └── src
            └── main
                ├── java10
                │   └── cn
                │       └── twle
                │           └── MultiReleaseJarTester.java
                ├── java8
                │   └── cn
                │       └── twle
                │           └── MultiReleaseJarTester.java
                └── java9
                    └── cn
                        └── twle
                            └── MultiReleaseJarTester.java
  1. 跳转到 multireleasejar 目录,并使用下面的命令编译三个不同的版本,其中,最重要的参数是 --release
        javac --release 10 -d java10  src/main/java10/cn/twle/MultiReleaseJarTester.java
        javac --release 9  -d java9   src/main/java9/cn/twle/MultiReleaseJarTester.java
        javac --release 8  -d java8   src/main/java8/cn/twle/MultiReleaseJarTester.java
`--release` 选项用于指定要编译目标的 JDK 版本。

编译完成后就可以看到 `multireleasejar` 的目录结构如下
        .
        ├── java10
        │   └── cn
        │       └── twle
        │           └── MultiReleaseJarTester.class
        ├── java8
        │   └── cn
        │       └── twle
        │           └── MultiReleaseJarTester.class
        ├── java9
        │   └── cn
        │       └── twle
        │           └── MultiReleaseJarTester.class
        └── src
            └── main
                ├── java10
                │   └── cn
                │       └── twle
                │           └── MultiReleaseJarTester.java
                ├── java8
                │   └── cn
                │       └── twle
                │           └── MultiReleaseJarTester.java
                └── java9
                    └── cn
                        └── twle
                            └── MultiReleaseJarTester.java
  1. 然后我们就可以使用下面的命令将这些不同版本的 MultiReleaseJarTester.class 封装到一个 JAR 里

    1. 首先跳转到 multireleasejar 目录,然后运行下面的命令首先创建一个默认版本,也就是 Java 8 版本
            jar -c -f  multireleasejar.jar --main-class=cn.twle.MultiReleaseJarTester -C java8 .
    运行完成后,就可以在当前目录看到一个 `multireleasejar.jar` 文件
    
    我们可以使用 `jar -tvf multireleasejar.jar` 查看文件中的内容
                [yufei@www.twle.cn multireleasejar]$ jar -tvf multireleasejar.jar 
                     0 Sun Sep 02 11:19:00 CST 2018 META-INF/
                   109 Sun Sep 02 11:19:00 CST 2018 META-INF/MANIFEST.MF
                     0 Sun Sep 02 10:51:40 CST 2018 cn/
                     0 Sun Sep 02 10:51:40 CST 2018 cn/twle/
                   714 Sun Sep 02 10:51:40 CST 2018 cn/twle/MultiReleaseJarTester.class
2.  然后依次运行下面的命令添加两个其它的版本
            jar -u -f multireleasejar.jar --release 10 -C java10 .
            jar -u -f multireleasejar.jar --release 9 -C java9 .
    执行第二条语句的时候会有一个警告,可以忽略
            [yufei@www.twle.cn multireleasejar]$ jar -u -f multireleasejar.jar --release 9 -C java9 .
            警告: 条目 META-INF/versions/10/cn/twle/MultiReleaseJarTester.class 包含与 jar 中的
            现有条目相同的类

好了,这样我们的多版本 multireleasejar.jar 就生成了,然后使用 jar -tvf multireleasejar.jar 查看文件中的内容如下

    [yufei@www.twle.cn multireleasejar]$ jar -tvf multireleasejar.jar 
         0 Sun Sep 02 11:20:24 CST 2018 META-INF/
       130 Sun Sep 02 11:20:40 CST 2018 META-INF/MANIFEST.MF
         0 Sun Sep 02 10:51:40 CST 2018 cn/
         0 Sun Sep 02 10:51:40 CST 2018 cn/twle/
       714 Sun Sep 02 10:51:40 CST 2018 cn/twle/MultiReleaseJarTester.class
         0 Sun Sep 02 10:21:20 CST 2018 META-INF/versions/10/
         0 Sun Sep 02 10:21:20 CST 2018 META-INF/versions/10/cn/
         0 Sun Sep 02 10:21:20 CST 2018 META-INF/versions/10/cn/twle/
       956 Sun Sep 02 10:21:20 CST 2018 META-INF/versions/10/cn/twle/MultiReleaseJarTester.class
         0 Sun Sep 02 10:22:06 CST 2018 META-INF/versions/9/
         0 Sun Sep 02 10:22:06 CST 2018 META-INF/versions/9/cn/
         0 Sun Sep 02 10:22:06 CST 2018 META-INF/versions/9/cn/twle/
       956 Sun Sep 02 10:22:06 CST 2018 META-INF/versions/9/cn/twle/MultiReleaseJarTester.class

运行多版本 JAR 包

首先在 Java 10 的环境下运行,输出结果如下

    [yufei@www.twle.cn multireleasejar]$ java -version
    java version "10.0.2" 2018-07-17
    Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
    Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)
    
    [yufei@www.twle.cn multireleasejar]$ java -jar multireleasejar.jar
    JDK version is:10.0.2

其次,在 Java 8 中运行,输出结果如下

    [yufei@www.twle.cn multireleasejar]$ java -version
    java version "1.8.0_45"
    Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
    Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
    
    [yufei@www.twle.cn multireleasejar]$ java -jar  multireleasejar.jar
    JDK version is:1.8.0_45

注意

  1. 首先,没必要特别区分 src/main/java10src/main/java9src/main/java8 这几个目录,如果代码都相同,只要一份即可

  2. 其次,多版本真正最重要的是编译的时候带上 --release [version] 版本号,用来指定编译版本

  3. 打包成 jar 的时候,三条命令可以放在一起,但最重要的是 --release [version] 一定要在 -C 参数之前,如果在之后,则有可能无效

    我折腾好久,就是因为犯了这个默认错误

  4. 一定要存在一个默认版本,一般情况下,可以使用主流版本为默认版本,这个默认版本可以不用添加 --release 参数


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文