jar中没有主清单属性_还在因 JDK 兼容问题发不同 JAR 包做兼容?MRJAR 了解一下?...

背景

Java 9 版本中增强了Jar 包多版本字节码文件格式支持,也就是说在同一个 Jar 包中我们可以包含多个 Java 版本的 class 文件,这样就能做到 Jar 包升级到新的 Java 版本(新特性 API 使用)时不用强迫使用方为了使用新 Jar 包而升级自己的业务模块 Java 版本,也不用针对不同最低支持 Java 版本提供不同的 Jar,真正的做到了一个 Jar 包兼容所有的目的。这样的 Jar 称为 MRJAR。

MRJAR 中的代码包含在不同版本 JDK 下编译的 class 文件。譬如使用 JDK9 编译的类可以调用 JDK9 提供的 API,而使用 JDK8 编译的类可以调用 JDK8 提供的 API,只要保证他们在 MRJAR 中的包名、类名、类对外调用都一致即可。

MRJAR 规则

一般典型情况下的 JAR 包内部包含 class 文件和一个属性META-INF/MANIFEST.MF文件,如下:

- jar-root
  - A.class
  - B.class
  - C.class
- META-INF
  - MANIFEST.MF

MRJAR 扩展自 JAR 的目录结构,扩展了META-INF目录以便存储特定 JDK 版本的 class 文件,META-INF目录包含一个版本子目录,其中可能包含许多子目录,每个目录的命名需要与 JDK 主要版本相同。譬如,对特定于 JDK9 的 class 可以放在META-INF/versions/9目录下,对特定于 JDK10 的 class可以放在META-INF/versions/10目录下等。所以一般典型情况下的 MRJAR 包内部大致如下:

- jar-root
  - A.class
  - B.class
  - C.class
- META-INF
  - MANIFEST.MF
  - versions
    - 9
      - A.class
      - D.class
    - 10
      - A.class
      - B.class

上面的例子中在不同 JDK 环境下运行表现如下:

  • 如果这个 MRJAR 在不支持 MRJAR 的 JDK 环境(譬如 JDK8)下使用,则会被自动兼容当做普通 JAR 使用,即META-INF/versions/目录下都被忽略,直接使用了 root 下的 class,所以无法访问 D。
  • 如果这个 MRJAR 在 JDK9 中使用,则只有 A、B、C、D 这几个 class 可以使用,且这里的 A、D 用的是META-INF/versions/9/下面的 class,其他用的 root 目录下的 class。
  • 对于 JDK10 来说,原理类同上面 JDK9,这里不多解释。只是说当我们在 JDK10 环境使用 C 类时搜索的顺序是先搜索META-INF/versions/10/下是否存在 C,如果不存在则搜索META-INF/versions/9/下是否存在 C,如果不存在则搜索根 root 目录下是否存在,这个查找顺序一定要明白。
  • 对 JDK11 来说,因为不存在META-INF/versions/11/,所以依次在低于自己的版本中搜索,在这里也就等同于在 JDK10 下被命中的类。

制作 MRJAR

JDK9 对生成 JAR 包的各种命令和工具都升级为支持 MRJAR,所以制作 MRJAR 最好直接使用 JDK9 开始的环境,其 jar 命令新增了一个参数为--release,语法如下:

//N代表一个JDK主版本,如JDK9中的9,且N值必须大于等于9;
//所有在--release N之后的文件都会被添加到MRJAR的META-INF/versions/N目录下;

jar  --release N 

假设现在我们准备好了一套 JDK8 的类和一套 JDK12 的类和编译成 class 的产物,如下:

//JDK8的源文件,编译产物目录假设为 jdk8/build/classes/
package cn.yan.mrjar;

public class JarUtil {
    public String func() {
        //JDK8 API实现功能
    }
}

//JDK12的源文件,编译产物目录假设为 jdk12/build/classes/
package cn.yan.mrjar;

public class JarUtil {
    public String func() {
        //JDK12 API实现功能
    }
}

接着我们对上面不同版本生成一个 MRJAR,如下命令:

jar --create --verbose --file test-out.jar
-C jdk8/build/classes .
--release 12 -C jdk12/build/classes .

这样就生成了一个 MRJAR,JDK12 的 JarUtil 类会被放进META-INF/versions/12/目录下,JDK8 的会被放进 root 根目录下。此时的 MRJAR 解压结构如下:

- jar-root
  - cn
    - yan
      - mrjar
        - JarUtil.class
- META-INF
  - MANIFEST.MF
  - versions
    - 9
      - cn
        - yan
          - mrjar
            - JarUtil.class

这样就能将上面制作好的的 MRJAR 在不同 JDK 环境下使用了,你说棒不棒,感觉有用来个在看的同时发给你的好基友呀。

8619d7e3220d9e28e15ece7c51dbbb14.png

0864bffc2e3a539c2ccd30c4d8797585.gif▼往期精彩回顾▼你知道 SimpleDateFormat 的性能问题怎么解决吗?推荐一波代码量、行数、提交量、作者等全维度统计神器

396539001bba2ab3eb00a1e5f375ea37.png点击左下角阅读原文查看历史经典技术问题汇总,看完顺手三连呀~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/498939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中哪些可以私有化_《Java基础学习笔记》JAVA修饰符之私有化(Private)

1,什么是private修饰符?private是权限修饰符,用于修饰类中的成员(成员变量,成员函数)。private修饰后的成员只在本类中有效。/* 例:* 将age私有化以后,类以外即使建立了对象也不能直接访问。* 但是人应用有…

python不定长参数_Python 函数参数之不定长参数(*args/**kwargs)、匿名函数 Lambda详解...

Python 调用函数时可使用的正式参数类型:必需参数 (位置参数)、关键字参数 (keyvalue)、默认参数 (keydefault)、不定长参数(可变参数)、强制位置参数(组合传参)Tips:有兴趣的还可以了解一下什么是形参?什么是实参?不定长参数 *a…

java第一天上班需要安装那些_明天第一天上班,应该带什么包啊

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼“下面拍卖的是一位道友在上古遗存下来的仙殿中得到的一盒炫迈!!!!!!!”大厅中顿时一片嘈杂.......拍卖行的老者摆了摆手示意让大家静一静然后慢悠…

java代码例子_程序员快速弄清Java异常体系,拒绝痛苦编程,开发效率加倍

知己知彼方能百战不殆,在小编初学Java时候特别怕程序报异常,经常会因为异常不知所措,相信这个问题应该是所有 初学者都会有的心理感受;如果你也有这种感受,那么只有一种解决方法: 迎难而上,攻克Java异常体系,长痛不如短痛,只要清楚了Java的异常体系,就不会再有这种感受了。下面…

java多条件判断_Java基础教程,第七讲,条件控制、循环语句、数组

学完此次课程,我能做什么?学完此次课程我们将掌握Java中的条件判断和多种循环语句,并且掌握数组的定义和初始化,以及几个常用的数组函数。学习此次课程,需要多久?10分钟课程内容和其他语言一样Java使用条件…

文件上传java前端怎么写_做一个文件上传,前端是ajax提交数据后台是java,这个错误怎么办...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼严重: Servlet.service() for servlet [dispatcherServlet] in context with path [/bazx] threw exception [Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to …

python对文件操作的相关函数_超全!python的文件和目录操作总结

文件的基本读写path rC:UsersBradyDocumentstmpwith open(path rdemo.txt, r, encodingutf-8) as f:content f.read()print(content)open()函数open(file, moder, buffering-1, encodingNone, errorsNone, newlineNone, closefdTrue, openerNone)Open file and return a cor…

qq机器人源码_基于Springcloud+vue+oAuth2.0全家桶模拟商城项目源码分享

项目介绍功能点:模拟商城,完整的购物流程、后端运营平台对前端业务的支撑,和对项目的运维,有各项的监控指标和运维指标。技术点:核心技术为springcloudvue两个全家桶实现,采取了取自开源用于开源的目标&…

java静态页面我都做不出_Java高并发:静态页面生成方案

提升网站性能的方式有很多,例如有效的使用缓存,生成静态页面等等。今天要说的就是生成静态页面的方式。这个也是我近期一直在搞的一个问题,近期在做使用html servlet做个人网站,为什么是这2个东西呢?1、直接用servlet…

python 工厂模式与单例模式_python基础单例模式 工厂模式 策略模式 观察者模式...

一、单例模式单例:单个实例,确保某个类只有一个实例存在举例:1、登录app,当前的登录对象,只能有一个2、音乐播放器,正在播放的歌曲类而言,只能有一个实例1 import my_util # 被导入的模块会从…

js sleep函数_简单而面试中又常见的知识点:JS执行机制

在开始讲解之前,我们先来看一段代码:console各位小伙伴觉得上面的结果输出会是多少呢?如果你没有了解过javascript的执行机制的话,上面的题目可能会让你崩溃。不过别着急,先往下看,我保证你看到最后&#x…

护卫神怎么增加php版本_护卫神php套件 php版本升级方法(php5.5.24)

最近小编开始学习研究win2008 r2的php环境配置,发现护卫神的php套件非常好用,安装简单,但是因为php版本不是最新的版本,所以就想将php升级下,因为新版的php修复了一些bug所以这里就分享下方法,需要的朋友可…

servlet中doget和dopost的区别_Servlet学习

一.HTTP协议浏览器 ----------------------------------------->服务器请求 http协议&#xff08;包含&#xff1a;1.请求行2.请求头3.空行4.请求实体&#xff09;url浏览器<-------------------------------------------服务器 响应htmlcssjsdata数据特点&#xff1a; 1…

python numpy dtype object_如何将(dtype = object)numpy数组值设置为Python列表,而不将numpy解释为值列表?...

我有一个dtype object数组,其中的值是Python列表或np.nan.我想用[无](不是无)替换np.nan的值.对于一个纯Python列表,我已经可以使用[x if(x不是np.nan)其他[无] for x in s],并且将数组转换为列表对我来说很好,但是出于好奇,我想知道如何使用numpy数组来完成这项工作.困难在于…

php curl跨域cookie_php使用curl带cookie访问一直失败求助

Launcher:感谢你在百忙中抽空帮我。刚才我做了个对比&#xff1a;1、使用Microsoft Network Monitor 监听apache发送的数据包2、使用Microsoft Network Monitor 截获ie登录目标后台3、使用Microsoft Network Monitor 截获firefox登录目标后台由第一点得到&#xff1a;cookie确实…

python如何用idle启动_Python从IDLE启动的方法

学习Python就要先学会安装和启动&#xff0c;目前Python的启动方法有两种&#xff0c;从IDLE启动是比较常见的&#xff0c;也是小码王老师今天要教大家的&#xff0c;广大家长、小朋友们一起来学习了解一下吧。在Start(开始)菜单中&#xff0c;可以看到“Python2.5”下面的“ID…

java xml 节点路径,SelectSingleNode使用XPath为已知良好的xml节点路径返回null

回答(9)2 years ago我强烈怀疑问题与名称空间有关 . 尝试摆脱名称空间&#xff0c;你会没事的 - 但显然这对你的实际情况没有帮助&#xff0c;我认为这个文件是固定的 .我不记得如何在XPath表达式中指定命名空间&#xff0c;但我确信这是问题所在 .编辑&#xff1a;好的&#x…

php fastcgi exp,nginx +phpfastcgi 环境下 导出excel文件,超时,数据被截断问题,解决...

nginx 错误日志显示&#xff0c;访问超时2015/09/16 07:18:43 [error] 2108#0: *6 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.138.7, server: localhost, request: "GET /test/index.php?mlists.e…

python爬虫软件安装不了_Mac os 下 python爬虫相关的库和软件的安装

由于最近正在放暑假&#xff0c;所以就自己开始学习python中有关爬虫的技术&#xff0c;因为发现其中需要安装许多库与软件所以就在这里记录一下以避免大家在安装时遇到一些不必要的坑。一. 相关软件的安装&#xff1a;1. homebrew:homebrew 是mac os系统下的包管理器由于功能齐…

php中文删除乱码部分,PHP中文乱码解决办法

一&#xff0e; 首先是PHP网页的编码1. php文件本身的编码与网页的编码应匹配a. 如果欲使用gb2312编码&#xff0c;那么php要输出头&#xff1a;header(“Content-Type: text/html; charsetgb2312")&#xff0c;静态页面添加&#xff0c;所有文件的编码格…