Java9版本新特性同一个Jar支持多JDK版本运行

目录
  • 一、基本使用方法
  • 二、真实的例子
    • java8代码
    • Java9代码
    • 编译
    • 运行Mainclass

我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注。期待您能关注我,我将把java 9 写成一系列的文章,大概十篇左右。

java9第一篇-可以在interface中定义私有方法了java9第二篇-Java9改进try-with-resources语法

本文内容:在Java 9增强了JAR多版本字节码文件格式的支持,同一个Jar包可以包含多个Java版本的class文件。使用这个功能,我们可以将应用程序/库升级到新的Java版本,而不必强迫用户升级到相同的Java版本。

一、基本使用方法

多版本的字节码发行jar包,需要在其MANIFEST.MF中做以下的声明:

Multi-Release: true

在jar包的META-INF/versions文件目录里面可以包含多个版本的class文件,编译结果目录结构如下:

jar root
  - A.class
  - B.class
  - META-INF
     - versions
        - 9
           - A.class

假设上文中的根目录是使用java 8 或之前版本编译的字节码文件A.calss。META-INF/versions/9/是使用java 9 编写的java代码的编译结果A.class。

如果jar包是在JDK 8的运行时环境下运行,将使用根目录下面的class文件进行程序运行。

如果jar包是在JDK 9的运行时环境下运行,将使用META-INF/versions/9/下面的class文件进行程序运行。

假设未来这个项目升级JDK 10,决定在A.java中使用Java 10的一些新特性,可以单独针对A.class进行语法升级,并将编译结果a.class放置在META-INF/versions/10/下面

jar root
  - A.class
  - B.class
  - META-INF
     - versions
        - 9
           - A.class
        - 10
           - A.class

现在,上面的jar包含了可以以三种Java版本运行的字节码文件,A.class兼容JDK 8、9、10。

二、真实的例子

java 8代码

下面的类文件代码我们让它运行在Java 8的环境下

package com.example;
public class IOUtil {
  public static String convertToString(InputStream inputStream) throws IOException {
      System.out.println("IOUtil 使用java 8 版本");
      Scanner scanner = new Scanner(inputStream, "UTF-8");
      String str = scanner.useDelimiter("\\A").next();
      scanner.close();
      return str;
  }
}

增加一个Main.java的应用程序入口文件,调用IOUtil.convertToString方法将InputStream转换成String。

package com.example;
public class Main {
  public static void main(String[] args) throws IOException {
          InputStream inputStream = new ByteArrayInputStream("测试字符串".getBytes());
          String result = IOUtil.convertToString(inputStream);
          System.out.println(result);
      }
}

Java 9代码

在Java 9 发布之后,我们决定使用Java 9 的新的语法重写IOUtil.convertToString方法。

package com.example;
public class IOUtil {
  public static String convertToString(InputStream inputStream) throws IOException {
      System.out.println("IOUtil 使用java 9 版本");
      try (inputStream) {  //Java9版本的增强try-with-resources
          String str = new String(inputStream.readAllBytes());
          return str;
      }
  }
}

如上的代码所示,我们使用了Java 9的两个新特性带有inputStream引用的try-with-resource块和新的InputStream.readAllBytes()方法。

编译

将Java8 、Java9的IOUtil.java代码分别在JDK8、JDK9的版本下分别编译成class字节码文件,并将class文件按照如下的目录结构打成保存,并打jar包。(先按java8版本打成jar包,然后修改MANIFEST.MF文件,添加java 9字节码class文件即可)

D:\multi-release-jar-example\my-lib-jar>tree /A /F
+---com
|   \---example
|           IOUtil.class
|           Main.class
|
\---META-INF
    |   MANIFEST.MF
    |
    \---versions
        \---9
            \---com
                \---example
                        IOUtil.class

运行 Main class

在JDK 9的环境下运行这个jar包

D:\multi-release-jar-example>java -cp my-lib.jar com.example.Main
IOUtil 使用java 9 版本
测试字符串

在JDK 8的环境下运行这个jar包

D:\multi-release-jar-example>C:\jdk1.8.0_151\bin\java -cp my-lib.jar com.example.Main
IOUtil 使用java 8 版本
测试字符串
(0)

相关推荐

  • Java9 集合工厂方法解析

    目录 使集合框架更便捷的工厂方法 集合框架增加工厂方法是必然的结果 早先的使用过程如下 也不得不提一下下面这些单语句表达式 下面是其原始类型的简明表达方式 一起来看看集合工厂方法 以下工厂方法已添加到List接口中 以下工厂方法已添加到Set接口中 以下是List和Set的示例 以下工厂方法则添加到Map接口中 下面是Map的ofEntries() 和entry()方法的示例 使集合框架更便捷的工厂方法 JEP269中提议,为集合框架增添一些工厂方法,来使创建不可变集合类与含有少量元素的Map变

  • java9版本特性资源自动关闭的语法增强

    目录 我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 写成一系列的文章,大概十篇左右. java9第一篇-可以在interface中定义私有方法了 在Java 9的版本中,对从JDK 7开始支持的try-with-resources语法进行了改进.虽然只是一个小小的改进,我仍希望把他介绍给你,我们一起来每天进步一点点. 一.先说Java7的try

  • Java9版本新特性同一个Jar支持多JDK版本运行

    目录 一.基本使用方法 二.真实的例子 java8代码 Java9代码 编译 运行Mainclass 我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 写成一系列的文章,大概十篇左右. java9第一篇-可以在interface中定义私有方法了java9第二篇-Java9改进try-with-resources语法 本文内容:在Java 9增强了J

  • Spring Boot2.3 新特性分层JAR的使用

    背景 在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况 影响 docker 镜像大小的因素,主要有以下三个方面: 基础镜像的大小 .尽量选择 alpine 作为基础镜像 减少操作系统内置软件 Dockerfile 指令层数. 这就要求我们优化 Dockerfile 能合并在一行的尽量合并等 应用 jar 的大小.这是今天要分享的重点内容 helloworld 镜像 我们先来基于 spring boot 2.3.0 构建一个最简单的 web helloworl

  • Spring各版本新特性的介绍

    Spring各个版本新特性 Spring3.1新特性 1.添加了引入环境profile功能 2.添加了@enable注解,使用特定功能 3.添加了对声明式缓存的支持,能够使用简单的注解声明缓存边界和规则 4.添加的用于构造器注入的c命名空间,类似与Spring2的p命名空间,用于对应属性注入 5.开始支持Servlet3.0,包括基于java配置中生命Servlet和Filter,不再只仅仅借助web.xml 6.改善对于JPA的支持,让JPA能在Spring中完整配置JPA,不必再使用pers

  • 浅谈react 16.8版本新特性以及对react开发的影响

    目录 react16.8版本更新 useEffect react16.8版本更新解决了什么问题 组件复用更便捷 hooks和reactdiff算法 总结 Facebook团队对社区上的MVC框架都不太满意的情况下,开发了一套开源的前端框架react,于2013年发布第一个版本. react最开始倡导函数式编程,使用function以及内部方法React.creactClass创建组件,之后在ES6推出之后,使用类组件Class构建包含生命周期的组件. react 16.8版本更新 react16

  • Go1.18新特性对泛型支持详解

    目录 1.泛型是什么 2.泛型类型的定义 2.1.声明一个自定义类型 2.2.内置的泛型类型any和comparable 2.3.泛型中的~符号是什么 1.泛型是什么 Go1.18增加了对泛型的支持,泛型是一种独立于使用的特定类型编写代码的方式.现在可以编写函数和类型适用于一组类型集合的任何一种.泛型生命周期只在编译期,旨在开发中减少重复代码的编写. 由于go属于静态强类型语言,例如在比较两个数的大小时,没有泛型的时候,仅仅只是传入类型不一样,我们就要再复制一份一样的函数,如果有了泛型就可以减少

  • webpack 4.0.0-beta.0版本新特性介绍

    近年来前端技术如雨后春笋般蓬勃发展,我们也在这个潮流下不断地学习.成长.前端技术的不断发展,给我们提供了许多的便利.例如:JSX的出现为我们提供了一个清晰.直观的方式来描述组件树,LESS/SASS的出现提高了我们书写css的能力,AMD/CommonJS/ES6 的出现为我们模块化开发提供了便利.然而,我们需要使用其它工具将这些工具转化成原生语言以运行在浏览器上.为了能够更好的将这些不同的资源整合到一起,我们就需要一个打包工具,webpack就是这个需求下的产物. webpack 可以看做是模

  • ThinkPHP3.1.3版本新特性概述

    ThinkPHP3.1.3版本有一些特性,还是值得关注的,下面来简单说下. 1.异常方面的改进 新版的ThinkPHP3.1.3重写了异常类ThinkException(其实是完全简化成了直接继承系统Exception类),并且把异常逻辑改进封装到Think类中.主要涉及到Think类的appException方法和halt函数. 并且改进后的异常处理支持系统致命错误的捕获,Think类增加了fatalError方法,原理是使用了 register_shutdown_function(array

  • Java9新特性对HTTP2协议支持与非阻塞HTTP API

    目录 一.HTTP/2简介 HTTP/2数据推送 目前支持 HTTP/2 的 Java HTTP 客户端 二.Java 9 的 HTTP/2 客户端 在阻塞模式下发送请求 以非阻塞模式发送请求(Java 9) 三.支持HTTP2的Push-Promise Frames 在HTTP/1.1 发布了16 年之后,IETF在2015年终于通过了HTTP/2 协议.HTTP/2协议旨在降低延迟,满足当今时代对于信息响应时间的要求.在这篇文章中,我会简要的对HTTP/2协议进行介绍,然后我们将重点放在研究

  • java9新特性Collection集合类的增强与优化方法示例

    目录 一.提供of()方法创建集合 1.1.构建Set集合对象 1.2.构建List集合对象 1.3.构建Map对象 1.4.使用Map.ofEntries()和Map.entry() 二.Arrays 2.1.Arrays.mismatch() 2.2.Arrays.equals() 我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 写成一系列的

  • Java9新特性Stream流API优化与增强

    目录 1.Stream.takeWhile(Predicate) 2.Stream.dropWhile(Predicate) 3.StreamStream.iterate(T,Predicate,UnaryOperator) 4.StreamStream.ofNullable(T) 5.IntStream,LongStream和DoubleStream方法 我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还

随机推荐