实战演练JDK的模块化机制
实战演练JDK的模块化机制
--楼兰带你聊最纯粹的Java
你发任你发,我用Java8。你用的JDK到什么版本了?很多开源框架都已经开始陆续升级JDK版本了。你对于JDK8往后陆陆续续更新的这些版本有什么感觉吗?
很多人会说其实并没有太多的感觉。JDK的新版本不断推出一些不痛不痒的新特性,但是基于JDK向下兼容的设计,只要我不关注这些花里胡哨的新特性,那么不管哪个版本的JDK,我都可以当做JDK8来用。
但是,其实,从JDK8往后,有一个机制,你是不得不了解的。因为这个机制,如果在你的项目中不启用还好。一旦启用了,会让你所有的业务代码必须进行一次脱胎换骨的变化。这个机制,就是自JDK9之后的模块化机制JPMS。
一、什么是模块化?
我们写的Java应用,都是以Jar包的形式发布的,所以对于Jar包,你一定习以为常。但是,如果你有一天打开一下JDK9以后的版本在你本地的安装目录,你会发现,JDK中那些熟悉的jar包,完全不见了。取而代之的是一些jmod文件。

甚至在熟悉的IDEA里,JDK的包下也不再是一个个Jar包,而变成了一个个与这些jmod文件对应的模块。

这些jmod文件是什么呢?
其实这些jmod文件可以认为是一种特殊的jar包。JMOD设计为在编译时间和链接时间使用,但不在运行时使用。你可以简单的理解为,这些jmod文件像jar包一样打包了class文件。但是你不能用java -cp或者java -m等机制使用这些jmod文件。
这就是Java的模块化机制的根基。从JDK8之后,整个JDK就已经用模块化的方式进行了重组。例如,安装JDK 17后,可以使用java --list-modules查看所有的系统模块。

甚至,JDK和JRE的关系,也已经发生了变化。在新版本的JDK中,应用程序可以只选择自己所需要的模块,打造一个自己定制的JRE,而不再需要引入JDK庞大的后台功能。
比如,我们如果只需要使用java.base模块中的一些基本功能,那么随时可以用以下指令打包出一个可以在服务器上运行的JRE:
jlink -p $JAVA_HOME/jmods --add-modules java.base --output basejre
这个basejre就可以像安装JDK一样,部署到服务器上运行。也可以基于这个JRE,运行Java程序。只不过,这个JRE中只包含了java.base模块中的这些类。像JDBC这样的其他模块的功能,就没法使用。
二、实战理解jmod
这种模块化机制既然是从JDK底层开始推出的,那么自然也可以运用到开发过程中。只不过,这种模块化机制对于很多传统的项目来说,还是有很多问题。因此,在应用中并没有严格铺开。
例如,你可以找一个现有的项目,将JDK版本升级到17后,就可以在项目中某个模块的classpath下添加个module-info.java文件。

但是,只要你在一个模块中添加了这个module-info.java文件。那么很多代码的编译过程,大概率就会出问题。这就是因为一旦启用了模块化机制,那么就需要对模块进行一些完整声明,保证所有应用都是一些独立,且边界明显的模块,而不再是一些零散的jar包了。
这个模块化机制怎么玩呢?接下来楼兰就带你简单玩一玩。
1、声明一个module
引入模块化机制后,应用㤇在每个模块的根目录下创建一个module-info.java文件,用来声明一个模块。在这个文件中,用module关键字,声明了一个模块。例如:
module roy.demomodule{
}
这样,当前目录下的所有package下 de代码,都将属于同一个module。module的名字必须全局唯一。至于具体的格式,没有强制要求。不过通常的惯例是类似于包结构,全部用小写,多个单词用.连接。
接下来就需要再roy.module中声明module的一些补充信息。这些补充信息主要包括:
- 对其他module的依赖关系
- 当前module对外开放的API
- 使用和提供的服务
2、require 声明module依赖
在module-info.java中首先要声明当前module需要依赖哪些外部模块。比如,如果你要使用junit,那么除了要在pom.xml中引入junit对应的依赖外,还需要在module-info.java中添加配置,否则项目编译就会报错。
requires requires junit;
这里要注意,对于显式声明了module-info.java的模块来说,模块名是显而易见的。但是对于没有声明module-info.java的非模块化jar包来说,默认就会创建具有jar包名称的模块。而这个名称还去掉版本号之后的标准包名。
比如,在demoModule1中,我引入了如下的junit依赖
<dependency>相关文章:
实战演练JDK的模块化机制
实战演练JDK的模块化机制--楼兰 带你聊最纯粹的Java 你发任你发,我用Java8。你用的JDK到什么版本了?很多开源框架都已经开始陆续升级JDK版本了。你对于JDK8往后陆陆续续更新的这些版本有什么感觉吗? 很多人会说其实并没有太多的感觉。JDK的新版本不断推出一些不痛不痒…...
jdk17+springboot3项目加密部署
最近项目需要在第三方服务器部署,由于没有交付源码。所以需要将项目加密后再部署。 网上找了一圈,发现xjar这个开源项目,可以将代码加密后进行部署。看了下正是我需要的。 于是按照文档打包加密,但启动的时候居然报错。 这个结…...
rm -rf 删除/下bin lib lib64 sbin软链接系统恢复
背景 不小心删除了/bin、/lib、/lib64和/sbin这些目录的软链接,导致系统中的各种命令都无法正常使用。在尝试多种方法后,包括添加环境变量和使用绝对路径执行命令无法恢复,最终不重装完美解决。 [rootcentos-8 /]# ll 总用量 36 drwxr-xr-x …...
并发与竞争
并发与竞争 并发与竞争的产生 Linux是一个多任务操作系统,肯定会存在多个任务共同操作同一段内存或者设备的情况,多个任务甚至中断都能访问的资源叫做共享资源,就和共享单车一样。在驱动开发中要注意对共享资源的保护,也就是要处…...
Java后端开发 ”Bug“ 分享——订单与优惠卷
“优惠券风波”:一段代码引发的线上事故 起因:优惠券功能上线 故事的开始源于公司新上线的一项促销活动——在用户未使用优惠券时,系统会自动赠送一张优惠券。这个功能不仅能提升用户体验,还能拉动平台的销售额。为了赶上活动上…...
Linux系统之tee命令的基本使用
Linux系统之tee命令的基本使用 一、tee命令介绍二、tee命令的使用帮助2.1 tee命令的help帮助2.2 tee命令帮助解释 三、tee命令的基本使用3.1 写入文件3.2 追加文件3.3 结合sudo命令3.4 结合EOF使用 四、注意事项 一、tee命令介绍 tee 是 Linux 和 Unix 系统中的一个命令&#x…...
idea 8年使用整理
文章目录 前言idea 8年使用整理1. 覆盖application配置2. 启动的时候设置编辑空间大小,并忽略最大空间3. 查询类的关系4. 查看这个方法的引用关系5. 查看方法的调用关系5.1. 查看被调用关系5.2. 查看调用关系 6. 方法分隔线7. 选择快捷键类型8. 代码预览插件9. JReb…...
多个微服务 Mybatis 过程中出现了Invalid bound statement (not found)的特殊问题
针对多个微服务的场景,记录一下这个特殊问题: 如果启动类上用了这个MapperScan注解 在resource 目录下必须建相同的 com.demo.biz.mapper 目录结构,否则会加载不到XML资源文件 。 并且切记是com/demo/biz 这样的格式创建,不要使用…...
k8s,service如何找到容器
Kubernetes之所以需要Service,一方面是因为Pod的IP不是固定的,另一方面则是因为一组Pod实例之间总会有负载均衡的需求 被selector选中的Pod,就称为Service的Endpoints,查看方式: kubectl get endpoints hostnames需要…...
观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?
大家好,我是锋哥。今天分享关于【观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用?】面试题。希望对大家有帮助; 观察者模式和发布-订阅模式有什么异同?它们在哪些情况下会被使用? 1000道 …...
docker compose deploy fate cluster
官方文档 写的不清晰 KubeFATE,用于生成部署脚本,链接 部署机就是下载了 KubeFATE的主机;运行机就是要安装fate容器的主机(部署机和运行机可以相同) 两个主机:并非必须 centos7,Ubuntu也行Doc…...
字节跳动Java开发面试题及参考答案(数据结构算法-手撕面试题)
怎么判断两个链表是否相交?怎么优化? 判断两个链表是否相交可以采用多种方法。 一种方法是使用双指针。首先分别遍历两个链表,得到两个链表的长度。然后让长链表的指针先走两个链表长度差的步数。之后,同时移动两个链表的指针,每次比较两个指针是否指向相同的节点。如果指…...
网工日记:FTP工作模式
FTP 基本概念 FTP(File Transfer Protocol)即文件传输协议,是用于在网络上进行文件传输的标准协议。它运行在 TCP/IP 协议栈之上,采用客户端 - 服务器(C/S)架构,通过在客户端和服务器之间建立控…...
unity使用代码在动画片段中添加event
unity使用代码在动画片段中添加event using UnityEngine;public static class AnimationHelper {/// <summary>/// 获取Animator状态对应的动画片段/// </summary>/// <param name"animator">Animator组件</param>/// <param name"…...
嵌入式轻量级开源操作系统:HeliOS的使用
嵌入式轻量级开源操作系统:HeliOS的使用 📍项目地址:https://github.com/heliosproj/HeliOS HeliOS项目是一个社区交付的开源项目,用于构建和维护HeliOS嵌入式操作系统(OS)。HeliOS是一个功能齐全的操作系统࿰…...
解决VMware的ubuntu22虚拟机没有网络
解决步骤 1.在 Windows 系统中,按 “WinR” 键,输入 “services.msc” 并回车,在服务列表中找到 “VMware DHCP Service” 和 “VMware NAT Service”,确保这两个服务已启动,若未启动则右键点击选择 “启动”…...
金属衬底介质片对平面波的反射-问题的解析求解和FEM求解
金属衬底介质片对平面波的反射-问题的解析求解和FEM求解 参考有限元从零单排系列4 代码参考了上面大佬文章提供的,但是部分计算系数错了,我改了下加了许多注释,便于大家理解。 书籍参考的电磁场有限元方法(金建铭),所用的公式都…...
2023 年 9 月青少年软编等考 C 语言四级真题解析
目录 T1. 酒鬼T2. 大盗T3. 核电站思路分析T4. 盒子与小球之二思路分析T1. 酒鬼 此题为 2021 年 3 月四级第一题原题,见 2021 年 3 月青少年软编等考 C 语言四级真题解析中的 T1。 T2. 大盗 此题为 2021 年 6 月四级第二题原题,见 2021 年 6 月青少年软编等考 C 语言四级真…...
C++的内存四区
文章目录 内存四区1.程序运行前1.1 代码区2.1 全局区2.2 示例 2.程序运行后1.1 栈区1.2 堆区 内存四区 1.程序运行前 在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域。该区域的数据在程序结束后由操作系统释放. 1.1 代码区 存放 CPU …...
Java爬虫技术:按关键字搜索VIP商品详情
在数字化时代,电子商务平台的竞争日益激烈,而精准的数据采集和分析成为了企业获取竞争优势的关键。对于电商平台而言,能够根据用户输入的关键字快速搜索并展示VIP商品的详细信息,不仅能够提升用户体验,还能够增加销售机…...
HunyuanVideo-FoleyGPU算力适配:RTX4090D与A100/H100推理性能对比
HunyuanVideo-FoleyGPU算力适配:RTX4090D与A100/H100推理性能对比 1. 引言 在视频生成与音效合成领域,HunyuanVideo-Foley作为一款集成视频生成和Foley音效合成的AI模型,对GPU算力有着极高的要求。本文将重点对比RTX4090D与专业级A100/H100…...
SiameseAOE模型AI编程助手场景应用:从需求描述生成代码注释要点
SiameseAOE模型AI编程助手场景应用:从需求描述生成代码注释要点 1. 引言 你有没有遇到过这种情况?产品经理或者业务方给你发来一段需求描述,文字洋洋洒洒,但核心的编程约束点却散落在各处,需要你像侦探一样去挖掘。比…...
利用Nanbeige 4.1-3B构建智能数据库查询优化器原型
利用Nanbeige 4.1-3B构建智能数据库查询优化器原型 最近在捣鼓一个挺有意思的项目,想看看大模型能不能帮我们解决一个老难题:数据库查询优化。这事儿听起来有点硬核,但说白了,就是让AI来当数据库的“老中医”,给它看看…...
FreeRTOS项目调试效率翻倍:给你的STM32F103工程嵌入一个轻量级日志模块(基于UART和StreamBuffer)
FreeRTOS项目调试效率革命:构建模块化日志系统的工程实践 调试嵌入式系统就像在黑暗森林中寻找萤火虫——你需要足够灵敏的工具捕捉那些稍纵即逝的线索。在STM32F103与FreeRTOS构成的典型嵌入式环境中,传统printf调试如同手持蜡烛探索,而模块…...
网站社交媒体推广对SEO有什么作用_图片和视频如何优化以提高搜索引擎收录
网站社交媒体推广对SEO有什么作用 在当前数字化时代,网站的SEO(搜索引擎优化)已经成为任何希望提升在线存在感的企业和个人的首要任务。SEO并不仅仅是关于在网站上优化文本内容。如今,社交媒体推广也在这一过程中发挥着越来越重要…...
海思SS524/SS522系列SDK编译实战:从零构建DVR开发环境
1. 海思SS524/SS522芯片与DVR开发入门 第一次接触海思SS524/SS522系列芯片时,我被它强大的视频处理能力震撼到了。这颗芯片简直就是为DVR产品量身定制的,特别是当你需要处理多路高清视频流时,它的优势就更加明显。SS524和SS522虽然型号不同&a…...
给STM32L5和LPC55S6x加把锁:手把手配置ARMv8-M TrustZone的SAU与内存分区
给STM32L5和LPC55S6x加把锁:手把手配置ARMv8-M TrustZone的SAU与内存分区 在物联网设备爆炸式增长的今天,安全已经从"可有可无"变成了"必不可少"。想象一下,你设计的智能门锁固件被轻易破解,或者医疗设备的敏…...
PHP跨文件传递参数的8种常见方法
以下是 PHP 中跨文件传递参数的 8 种常见方法,按场景和安全性分类整理,附详细说明和示例代码: 一、超全局变量(适合请求间数据共享) 1. $_GET / $_POST 用途:通过 URL 或表单提交传递参数(客户…...
28、什么是防抖和节流?有什么区别?如何实现?
这是前端面试里的高频题,几乎每个做过交互、性能优化的人都会被问到。 如果你只是回答“防抖就是延迟执行,节流就是固定时间执行一次”,只能算及格。 如果你能讲清楚: 概念区别适用场景实现方式进阶参数面试表达方式 那这题会答…...
C#怎么批量删除指定格式文件_C#如何遍历清空目录【干货】
应先用Directory.GetFiles精准匹配再逐个删除,避免Directory.Delete误删或报错;需处理权限、占用、只读等异常,并注意中文路径、ACL跳过、句柄未释放等问题。用 Directory.GetFiles 精准匹配再删,别直接 Directory.Delete批量删指…...
