java:使用Multi-Release Jar改造Java 1.7项目增加module-info.class以全面合规Java 9模块化规范

news2024/11/12 12:39:37

common-java是一个我维护了好多年的一个基础项目,编译目标为Java 1.7
现在整个团队的项目要做Java 9以上的技术迁移准备,就需要对这个在内部各项目中被广泛引用的基础项目进行改造,以适合Java 9的模块化规范。

Automatic-Module-Name

Java 9的模块化规范(即Java Platform Module System [JPMS])要求在项目中有module-info.java,
会在module-info.java中定义模块名
module-info.java定义模块名示例如下

module your.module.name{
	//
}

JPMS可以兼容Java 1.7或1.8的依赖库.
在Java 9平台如果一个库没有module-info.class,那么会将它识别为自动模块(automatic module).会根据jar包的名字自动生成模块名(Module Name).
因为这个模块名是根据Jar包名字计算出来的,是不稳定的(比如手工改了Jar包文件名,模块名也会自动改为).
所以这不是JPMS建议的方式,所以在Java 9环境中引用自动模块时,编译过程会输出警告.

[WARNING] ******************************************************************************************************************************************************************************************************************************************************************************************************
[WARNING] * Required filename-based automodules detected: [guava-20.0.jar, jsr305-1.3.9.jar, fastjson-1.2.83.jar, jackson-databind-2.8.10.jar, jackson-core-2.8.10.jar, sql2java-base-3.29.3.jar, openbeans-1.0.2.jar, jcifs-ng-2.1.2.jar]. Please don’t publish this project to a public artifact repository! *
[WARNING] ******************************************************************************************************************************************************************************************************************************************************************************************************

对于一个编译目标为Java 1.7或1.8的项目,如果项目结构与Java 9的模块化要求不存在冲突.升级到Java 9并不复杂.
只要如下加一个maven-jar-plugin插件的配置,指定在生成Jar包中META-INF/MANIFEST.MF中增加Automatic-Module-Name定义,显式指定自动模块的名字.就可以让一个项目基本适合JPMS.可以正常被其他Java 9项目在module-info.java中引用。

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-jar-plugin</artifactId>
					<version>3.4.2</version>
					<configuration>
						<archive>
							<manifestEntries>
								<Automatic-Module-Name>your.module.name</Automatic-Module-Name>
							</manifestEntries>
						</archive>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>	
	</build>

Multi-Release Jar

采用上一节的方案生成的jar,在被Java 9项目引用时还会输出警告,示例如下:

[WARNING] /J:/javadocreader9/src/main/java/module-info.java:[7,34] 需要自动模块的过渡指令

引用自动模块报警的项目的module-info.java定义:

module com.gitee.l0km.javadocreader{
	exports com.gitee.l0km.javadocreader;
	requires java.desktop;
	requires transitive  jdk.javadoc;
	requires static com.google.common;
	requires transitive com4j.base2;
	requires transitive com4j.base;// [WARNING]:需要自动模块的过渡指令
	requires aocache;
	requires org.slf4j;
}

如果只是想消除这行警告,只需要将requires transitive com4j.base;改为requires static com4j.base;

也就是说对于一个Java 9项目如果module-info.java中引用了有Automatic-Module-Name定义了模块名的项目jar包,也仍然会有编译警告,它仍然不是JPMS满意的jar包.

要想让一个项目完全符合JPMS规范,就需要为它定义module-info.java,在module-info.java中显式定义项目的模块名,导出的包名等等.

参见 《Java 模块化指南》

定义module-info.java这本身不是问题.
问题在于我们的系统中还有一些android设备仍然在使用Java 1.7。
common-java这个项目也仍然被运行在这些Java 1.7的android设备上的APP引用.
如果增加module-info.java定义,项目的编译目标就要升级到Java 9,就不能用于Java 1.7的平台了.这肯定是不能接受的.

有没有一个两全其美的解决方案呢?

Multi-Release Jar (MRJAR)(多版本兼容Jar)是Java 9的一个新特性,就是为了解决这个麻烦而诞生的。
它允许将支持多个Java版本不特性的版本打包在同一个Jar包中,系统在运行时自动根据当前的Java版本,从Jar包选择对应Java版本的class加载.

即扩展 JAR 文件格式以允许多个特定于 Java 版本的 类文件的版本共存于单个存档(Jar)中。
详细说明参见:《JEP 238: Multi-Release JAR Files》

Multi-Release Jar (MRJAR)这个特性,事儿就好办了,还以common-java这个项目为例,分两个步骤:

(一) java.9

首先定义module-info.java
创建一个一个源文件夹${project.basedir}/src/main/java.9,在该文件夹下定义module-info.java
比如:

module com4j.base{
    exports com.gitee.l0km.com4j.base;
    exports com.gitee.l0km.com4j.base.encrypt;
    exports com.gitee.l0km.com4j.base.exception;
    exports com.gitee.l0km.com4j.base.web;

    requires static jackson.annotations;
}

(二)Multi-Release

更新pom.xml,如下增加maven-jar-pluginmaven-compiler-plugin插件定义

	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.13.0</version>
					<executions>
						<execution>
							<id>default-compile-java-7</id>
							<goals>
								<goal>compile</goal>
							</goals>
							<configuration>
								<release>7</release>
								<compileSourceRoots>
									<compileSourceRoot>${project.basedir}/src/main/java</compileSourceRoot>
								</compileSourceRoots>
							</configuration>
						</execution>
						<execution>
							<id>compile-java-9</id>
							<goals>
								<goal>compile</goal>
							</goals>
							<configuration>
								<release>9</release>
								<compileSourceRoots>
									<compileSourceRoot>${project.basedir}/src/main/java.9</compileSourceRoot>
								</compileSourceRoots>
								<multiReleaseOutput>true</multiReleaseOutput>
							</configuration>
						</execution>
					</executions>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-jar-plugin</artifactId>
					<version>3.4.2</version>
					<configuration>
						<archive>
							<manifestEntries>
								<Multi-Release>true</Multi-Release>
							</manifestEntries>
						</archive>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>

maven-jar-plugin插件中定义Multi-Release,即在生成的Jar中META-INF/MANIFEST.MF中定义Multi-Release为true,将Jar标志为支持Multi-Release.
maven-compiler-plugin插件中定义两个执行过程(<execution></execution>),
一个execution (default-compile-java-7)用于Java 1.7版本的编译,编译${project.basedir}/src/main/java源码文件夹下的所有主要代码.
另一个execution(compile-java-9)用于编译${project.basedir}/src/main/java.9,只有一个文件module-info.java,编译生成人代码保存到META-INF/versions/9,即Java 9对应的版本.

重新执行maven install生成的Jar包如下,Jar中除了:META-INF/versions/9/module-info.class外,主要代码代码的编译目标仍然为Java 1.7。因为有module-info.class提供模块定义,该Jar包在Java 9以上的平台上运行时,就是个符合JPMS要求的Module.
在这里插入图片描述
META-INF/MANIFEST.MF中定义如下:

Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.4.2
Build-Jdk-Spec: 19
Multi-Release: true

注意

如上改造了pom.xml后,不能再使用Java 1.7或1.8编译器构建项目,要使用Java 9以上编译器(我用的是Java 19)

common-java码云仓库位置:https://gitee.com/l0km/common-java

参考资料

《JDK 9 模块化系统 (Java Platform Module System) 和 多版本兼容 Jar (Multi-Release Jar)》

《JEP 238: Multi-Release JAR Files》

《Java 模块化指南》

《compiler:compile》
《Apache Maven JAR Plugin》

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

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

相关文章

力扣题库——75.颜色分类

这道题采用三路快速排序&#xff0c;快速排序思路看这里快速排序。将数列分为三组&#xff1a;小于基准、等于基准、大于基准。和快排一样&#xff0c;对左右递归进行快速排序。 先将题目简化&#xff0c;如果只有数字0和1&#xff0c;扫描一遍数组&#xff0c;遇到数字1不用管…

python - leetcode【数据结构-算法】-入门/通关手册

python的算法入门/通关/手册 前言&#xff1a;算法通关手册&#xff08;LeetCode&#xff09;-githubHello 算法&#xff1a;python数据结构和算法 - 中文版The Algorithms - Python最后刷题思维: python-leetcode刷题常用语法&#xff1a;变量定义&#xff1a;逻辑与或非和按位…

使用 Flask 和 ONLYOFFICE 实现文档在线编辑功能

提示&#xff1a;CSDN 博主测评ONLYOFFICE 文章目录 引言技术栈环境准备安装 ONLYOFFICE 文档服务器获取 API 密钥安装 Flask 和 Requests 创建 Flask 应用项目结构编写 app.py创建模板 templates/index.html 运行应用功能详解文档上传生成编辑器 URL显示编辑器回调处理 安全性…

EasyUI弹出框行编辑,通过下拉框实现内容联动

EasyUI弹出框行编辑&#xff0c;通过下拉框实现内容联动 需求 实现用户支付方式配置&#xff0c;当弹出框加载出来的时候&#xff0c;显示用户现有的支付方式&#xff0c;datagrid的第一列为conbobox,下来选择之后实现后面的数据直接填充&#xff1b; 点击新增&#xff1a;新…

C# 选择导入文件的路径、导出文件的路径

通过C#代码&#xff0c;调出windows风格的文件选择对话框和存储文件对话框。提供界面来选择文件的位置&#xff0c;并将完整路径以字符串形式返回。 1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff…

数据结构-并查集专题(1)

一、前言 因为要开始准备年底的校赛和明年年初的ACM、蓝桥杯、天梯赛&#xff0c;于是开始按专题梳理一下对应的知识点&#xff0c;先从简单入门又值得记录的内容开始&#xff0c;并查集首当其冲。 二、我的模板 虽然说是借用了jiangly鸽鸽的板子&#xff0c;但是自己也小做…

二手交易平台测试用例设计和执行

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;追求开源思想和学无止境思想一直在提升技术的路上 &#x1f384; &#x1f308;涉及的领域有&#xff1a;Java、Python、微服务架构和分布式架构思想、基本算法编程&#x1f308; &#x1f386;喜欢的朋友可…

计算机图形学论文 | 多边形中的点可见性快速算法

&#x1f98c;&#x1f98c;&#x1f98c;读论文 &#x1f428;&#x1f428;摘要 针对点的可见性计算这一计算几何中的基础问题&#xff0c;提出一种支持任意查询点的可见多边形快速计算的基于多边形Voronoi图的点可见性算法。以与Voronoi骨架路径对应的Voronoi通道概念&…

Redis 高并发分布式锁实战

目录 环境准备 一 . Redis 安装 二&#xff1a;Spring boot 项目准备 三&#xff1a;nginx 安装 四&#xff1a;Jmeter 下载和配置 案例实战 优化一&#xff1a;加 synchronized 锁 优化二&#xff1a;使用 redis 的 setnx 实现分布式锁 优化三&#xff1a;使用 Lua 脚本…

LLM大模型学习精华系列:VLLM性能优化部署实践——全面加速从推理到部署的流程

训练后的模型会用于推理或者部署。推理即使用模型用输入获得输出的过程&#xff0c;部署是将模型发布到恒定运行的环境中推理的过程。一般来说&#xff0c;LLM的推理可以直接使用PyTorch代码、使用[VLLM]等框架&#xff0c;也可以使用[llama.cpp]等c推理框架。 常见推理方法 G…

【大数据学习 | kafka高级部分】kafka的快速读写

1. 追加写 根据以上的部分我们发现存储的方式比较有规划是对于后续查询非常便捷的&#xff0c;但是这样存储是不是会更加消耗存储性能呢&#xff1f; 其实kafka的数据存储是追加形式的&#xff0c;也就是数据在存储到文件中的时候是以追加方式拼接到文件末尾的&#xff0c;这…

SpringCloud篇(微服务)

目录 一、认识微服务 1. 单体架构 2. 分布式架构 3. 微服务 3.1. 特点 3.2. 优点 3.3 缺点 二、微服务设计、拆分原则 1. AKF 拆分原则 2. Y轴&#xff08;功能&#xff09;关注应用中功能划分&#xff0c;基于不同的业务拆分 3. X轴&#xff08;水平扩展&#xff09…

Hive简介 | 体系结构

Hive简介 Hive 是一个框架&#xff0c;可以通过编写sql的方式&#xff0c;自动的编译为MR任务的一个工具。 在这个世界上&#xff0c;会写SQL的人远远大于会写java代码的人&#xff0c;所以假如可以将MR通过sql实现&#xff0c;这个将是一个巨大的市场&#xff0c;FaceBook就这…

高校宿舍信息管理系统小程序

作者主页&#xff1a;编程千纸鹤 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参…

森林防火责任大于天,可视化监控大屏让隐患无处遁形。

在大自然的生态系统中&#xff0c;森林是地球之肺&#xff0c;为我们提供着清新的空气、丰富的资源和优美的环境。然而&#xff0c;森林火灾却如同一场可怕的灾难&#xff0c;随时可能摧毁这片宝贵的绿色财富。森林防火责任大于天&#xff0c;而可视化监控大屏的出现&#xff0…

“穿梭于容器之间:C++ STL迭代器的艺术之旅”

引言&#xff1a; 迭代器&#xff08;Iterator&#xff09;是C STL&#xff08;标准模板库&#xff09;中非常重要的一部分&#xff0c;它提供了一种统一的方式来遍历容器中的元素。无论容器是数组、链表、树还是其他数据结构&#xff0c;迭代器都能够以一致的方式访问这些数据…

el-scrollbar 动态更新内容 鼠标滚轮无效

有以下功能逻辑&#xff0c;实现了一个时间轴组件&#xff0c;点击、-号后像地图那样放大组件以显示不同的UI。 默认显示年月&#xff1a; 当点击一下加号时切换为年&#xff1a; 当点击减号时切换为日&#xff1a; 即加号、减号点击就是在年月日显示进行切换。给Scrollvie…

Linux【基础篇】

-- 原生罪 linux的入门安装学习 什么是操作系统&#xff1f; 用户通过操作系统和计算机硬件联系使用。桥梁~ 什么是Linux&#xff1f; 他是一套开放源代码&#xff08;在互联网上找到Linux系统的源代码&#xff0c;C语言写出的软件&#xff09;&#xff0c;可以自由 传播&…

C++类(5)

1.<<和>>操作符重载 我们该如何重载操作符<<和>>呢&#xff1f; 如果在类里面&#xff0c; void operator<<(ostream& out) {out << _year << "年" << _month << "月" << _day <&l…

【MM-Align】学习基于输运的最优对齐动力学,快速准确地推断缺失模态序列

代码地址 - > github传送 abstract 现有的多模态任务主要针对完整的输入模态设置&#xff0c;即每个模态在训练集和测试集中要么是完整的&#xff0c;要么是完全缺失的。然而&#xff0c;随机缺失的情况仍然没有得到充分的研究。在本文中&#xff0c;我们提出了一种新的方…