当前位置: 首页 > java >正文

Java 模块化系统(JPMS)

在介绍一个

Java 模块化系统(JPMS)

一、理论说明

1. 模块化的定义

Java 模块化系统(Java Platform Module System, JPMS)是 Java 9 引入的一项重大特性,它为 Java 平台和应用程序提供了模块化架构。模块化允许将代码组织成独立的模块单元,每个模块明确声明其依赖关系和对外暴露的 API,从而提高代码的可维护性、安全性和可扩展性。

2. 模块化与传统 JAR 的区别

特性传统 JAR模块化 JAR
结构类的集合,无明确边界显式声明模块名、依赖和导出
依赖管理全路径类名,容易冲突显式声明 requires,编译时检查
访问控制仅包可见性(public/protected模块级导出(exports),更精细控制
加载机制全盘加载所有 JAR基于模块图,按需加载
安全性类路径污染风险更严格的访问控制,减少反射滥用

二、核心概念

1. 模块声明(module-info.java

每个模块必须包含一个 module-info.java 文件,用于声明模块名、依赖和导出的包。

// module-info.java
module com.example.myapp {// 声明依赖的模块requires java.base;requires java.sql;// 导出包供其他模块使用exports com.example.api;// 可选:仅允许特定模块访问exports com.example.internal to com.example.client;// 声明服务提供者provides com.example.Service with com.example.impl.ServiceImpl;// 使用服务uses com.example.Service;
}

2. 模块路径(Module Path)

模块化系统引入了新的类路径概念 —— 模块路径,用于替代传统的类路径(Classpath)。模块路径上的 JAR 文件必须是模块化的(包含 module-info.class)。

# 编译模块化应用
javac --module-path mods -d out $(find src -name "*.java")# 运行模块化应用
java --module-path mods --module com.example.myapp/com.example.Main

三、模块类型

1. 命名模块(Named Modules)

显式声明了 module-info.java 的模块,如:

module com.example.util {exports com.example.util;
}

2. 自动模块(Automatic Modules)

传统 JAR 文件在模块路径上会被自动转换为自动模块,模块名由 JAR 文件名推导(如 my-library-1.0.jar 变为 my.library)。自动模块隐式导出所有包,依赖所有其他模块。

3. 系统模块(System Modules)

Java 平台自身的模块(如 java.basejava.sql),由 JDK 提供。

四、服务机制(Service)

模块系统提供了服务发现机制,允许模块声明和使用服务接口,解耦服务提供者和使用者。

1. 定义服务接口

// com.example.api.Service.java
package com.example.api;public interface Service {void execute();
}

2. 实现服务

// com.example.impl.ServiceImpl.java
package com.example.impl;import com.example.api.Service;public class ServiceImpl implements Service {@Overridepublic void execute() {System.out.println("执行服务");}
}

3. 声明服务提供者

在提供者模块的 module-info.java 中声明:

module com.example.impl {exports com.example.impl;provides com.example.api.Service with com.example.impl.ServiceImpl;
}

4. 使用服务

在使用者模块中通过 ServiceLoader 加载服务:

import com.example.api.Service;
import java.util.ServiceLoader;public class Main {public static void main(String[] args) {ServiceLoader<Service> loader = ServiceLoader.load(Service.class);loader.forEach(Service::execute);}
}

五、模块化优势

1. 强封装性

模块仅导出明确声明的包,内部实现对外部不可见,减少了意外依赖。

2. 依赖清晰

模块间依赖显式声明,编译时检查,避免类路径冲突和版本地狱。

3. 性能优化

JVM 可以基于模块图进行更高效的类加载和资源分配。

4. 安全性增强

通过限制反射访问和更严格的访问控制,减少安全漏洞。

5. 可维护性提升

代码按功能划分为独立模块,便于团队协作和系统演进。

六、应用实例

1. 创建简单模块化应用

假设有两个模块:com.example.api 和 com.example.impl

com.example.api 模块
// module-info.java
module com.example.api {exports com.example.api;
}// com.example.api.Greeting.java
package com.example.api;public interface Greeting {String sayHello();
}
com.example.impl 模块
// module-info.java
module com.example.impl {requires com.example.api;exports com.example.impl;
}// com.example.impl.EnglishGreeting.java
package com.example.impl;import com.example.api.Greeting;public class EnglishGreeting implements Greeting {@Overridepublic String sayHello() {return "Hello, World!";}
}
编译和运行
# 编译模块
javac -d api-module src/api/module-info.java src/api/com/example/api/*.java
javac --module-path api-module -d impl-module src/impl/module-info.java src/impl/com/example/impl/*.java# 运行应用
java --module-path api-module:impl-module -m com.example.impl/com.example.impl.Main

七、面试题

题目;

答案:

八、自我总结

Java 模块化系统(JPMS)为大型应用和平台提供了更现代的架构模式,通过显式的模块定义和依赖管理,解决了传统 Java 项目中的类路径混乱、依赖冲突和封装不足等问题。关键要点包括:

  1. 模块声明:使用 module-info.java 定义模块边界和依赖关系。
  2. 服务机制:通过 ServiceLoader 实现松耦合的服务发现。
  3. 模块路径:替代传统类路径,提供更严格的依赖管理。
  4. 兼容性:支持与传统 JAR 文件混合使用(自动模块)。

在实际应用中,模块化适合大型项目和框架开发,能够显著提高代码质量和可维护性。但对于小型应用,可能会增加额外的复杂度,需权衡使用。JPMS 是 Java 平台向现代化演进的重要一步,也是未来 Java 生态系统的基础。

http://www.xdnf.cn/news/8184.html

相关文章:

  • 点云(point cloud):自动驾驶的“三维扫描图“
  • SQLSERVER数据库表分区学习(未在项目上使用)
  • 6:OpenCV—图像滤波
  • 设置标签(tag)并推送到GitHub
  • 并发编程 之 Java内存模型、AQS详解:AQS设计思想、Unsafe
  • 基于自动编码器的图像融合方法
  • 腾讯2025年校招笔试真题手撕(一)
  • 一图胜千言:Typora中Mermaid图表语法全解析
  • Qwen3技术报告笔记
  • 《数据结构笔记二》:顺序表
  • 【技术追踪】ADDP:通过交替去噪扩散过程学习用于图像识别和生成的通用表示(ICLR-2024)
  • Java中static关键字深度解析:从入门到高阶实战
  • 碰一碰发视频源码搭建定制化开发详解,支持OEM
  • One-shot和Zero-shot的区别以及使用场景
  • 嵌入式STM32学习——串口USART 2.3(串口发送数据控制LED灯)
  • 一文读懂GRPC
  • Django的请求和响应+template模板
  • CentOS7/Ubuntu SSH配置允许ROOT密码登录
  • LeRobot的机器人控制系统(上)
  • 无人机避障——深蓝学院浙大栅格地图以及ESDF地图内容
  • BlazeMeter录制jmeter脚本
  • 2025年系统架构师---综合知识卷
  • FreeBSD14.2因为爆内存而导致Xfce4视窗被卡,桌面变黑色,只能看到鼠标在窗体中心,鼠标无反应,键盘无反应
  • 03_基础篇-NumPy(下):深度学习中的常用操作
  • deepseek调用
  • QT ui控件setEnabled(false) 作用
  • SpringBoot系列之OpenAI API 创建智能博客评论助手
  • 人工智能培训:解锁未来职场竞争力的核心路径与课程内容解析
  • 【JAVA基础】什么情况下可以直接使用类名.方法名调用方法?
  • 【VLNs篇】05:TGS-在无地图室外环境中使用视觉语言模型进行轨迹生成和选择