JPMS通过module-info.java强制显式声明依赖与导出、强封装包可见性、启动时验证模块图,彻底取代隐式类路径,杜绝类冲突与非法访问。

Java 模块化系统(JPMS)通过强制显式声明、强封装机制和模块图验证,从根源上切断“类路径地狱”的形成链条,不再依赖扁平、隐式、易冲突的类路径加载方式。
用模块边界替代类路径扁平结构
类路径把所有 JAR 和 class 文件摊在一条线上,JVM 按顺序扫描,同名类只取第一个,冲突静默发生。模块路径则要求每个代码单元必须定义为独立模块,JVM 启动时先构建模块图(module graph),再按依赖拓扑加载——没有“谁先谁后”的运气成分,只有“是否可达”的确定性。
- 模块间通信必须通过
requires显式声明依赖,未声明即不可见 - 类路径上的传统 JAR 被自动转为“自动模块”(automatic module),虽可被引用,但不提供封装、不支持
exports控制,仅作过渡兼容 - 同名类若同时存在于模块路径与类路径,模块路径版本优先,类路径版本被彻底忽略——消除加载歧义
靠导出控制(exports)实现真正封装
类路径下任何包里的 public 类,只要能被类加载器找到,就能被任意其他类反射或直接调用。模块系统改写规则:即使类是 public 的,若其所在包未在 module-info.java 中 exports,外部模块就无法访问,编译期直接报错。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
exports com.example.service;—— 仅该包对所有依赖模块可见 -
exports com.example.internal to com.example.app;—— 精确限定仅某模块可访问,实现细粒度隔离 - 未导出的包,连运行时反射(除非用
open)都无法穿透,杜绝“内部 API 被滥用”导致的升级断裂
依赖完整性在编译期和启动期双重校验
类路径项目常到运行时才爆出 NoClassDefFoundError 或 LinkageError,因为缺失依赖或版本错配只能靠试错发现。模块系统把校验前移到两个关键节点:
立即学习“Java免费学习笔记(深入)”;
- 编译阶段:
javac --module-path会检查requires的模块是否存在、导出包是否包含所需类型 - 启动阶段:
java --module-path构建模块图时,验证所有requires是否满足、是否存在循环依赖、是否有未解析的模块约束 - 一旦失败,JVM 拒绝启动,并给出明确路径提示,例如 “module A requires B, but B not found in module path”
模块路径与类路径严格分治,不混搭
Java 9+ 明确区分两种路径语义:模块路径用于模块化组件,类路径保留给遗留库。两者共存时,JVM 不尝试融合,而是划定清晰边界:
- 模块路径中的类,必须经
requires才能被其他模块使用;不能靠类路径“偷偷塞进来” - 类路径上的类,无法访问模块内未导出的包,也无法被模块内代码以模块方式依赖(只能走传统 classload)
- 这种分离避免了“一半模块化、一半类路径”带来的行为不可预测性,让迁移可分步、可验证

















