module-path 是 java 模块系统(jpms)的模块加载路径,与 classpath 并行而非替代;前者加载命名/自动模块并强制依赖声明与包可见性控制,后者将所有类归入 unnamed module 且无访问约束。

module-path 是什么,和 classpath 本质区别在哪
module-path 不是 classpath 的升级版,而是两套并行的加载机制:一个管“模块”,一个管“类”。JVM 启动时,只要指定了 -p 或 --module-path,它就启用模块系统(JPMS),所有在 module-path 下的 JAR 若含 module-info.class,就被当作命名模块处理;而 classpath 下的所有内容——无论是否模块化——全被塞进一个叫 unnamed module 的“大杂烩模块”里。
关键差异不是路径写法,而是语义:classpath 没有依赖声明、没有包可见性控制、不校验导出;module-path 要求模块显式 requires 和 exports,编译期就能发现“用了别人没导出的包”这类问题。
命令行里怎么用 -p 和 -cp,顺序错了会怎样
两者可以同时存在,但 JVM 有明确优先级:模块路径 > 类路径。比如执行:java -p mods/ -cp lib/ com.example.Main
若 com.example.Main 依赖 utils.jar,且该 JAR 同时出现在 mods/ 和 lib/ 中,JVM 一定加载 mods/ 下那个——哪怕它版本更旧、API 更少,也照用不误。
-
-p(等价于--module-path)只影响模块解析,不参与传统类查找 -
-cp(等价于--class-path)只影响 unnamed module 的类加载,对模块内requires的依赖无效 - 不能混用:把模块化 JAR 放进
-cp,module-info.class直接被忽略,退化成普通 JAR;把非模块化 JAR 放进-p,它变成自动模块(automatic module),名字取自 JAR 文件名,且自动导出所有包——可能意外暴露内部类
IDE(如 Eclipse)里加依赖,选 Classpath 还是 Modulepath?
Eclipse 的 Build Path 面板里,“Classpath” 和 “Modulepath” 是两个独立标签页,不是开关切换。选错位置,等于告诉 JVM 用错加载规则。
立即学习“Java免费学习笔记(深入)”;
- 项目没
module-info.java?只能走 Classpath —— 即使 JDK 是 17,模块系统也不会激活 - 项目有
module-info.java,但依赖库是老版本 Spring(无模块信息)?必须放 Modulepath,它会转为自动模块;放 Classpath 反而会导致NoClassDefFoundError,因为模块内代码看不到 unnamed module 的类 - 同一个 JAR 绝对不要既拖进 Classpath 又拖进 Modulepath,否则触发 split package 报错:
error: the unnamed module reads package xxx from both A and B
为什么明明写了 module-info.java,还是报 “package not exported”
常见原因不是语法错,而是路径配置和模块解析没对上。典型场景:
- 你把
my-api.jar放进了-cp,但my-impl.jar在-p里且requires my.api→ 失败:impl 模块根本找不到 my.api 模块,因为它在 unnamed module 里 -
my-api.jar确实在-p,但它的module-info.java写的是module my.api { exports com.example.api; },而调用方 import 的是com.example.api.v2→ 包没导出,报错 - 用了 Maven,但
maven-compiler-plugin没配<release>11</release>或没开<enablepreview>true</enablepreview>(如果用了新特性),导致编译出的module-info.class版本不匹配运行时 JDK
最易被忽略的一点:模块路径下的 JAR 必须能被 JVM 完整解析——哪怕只是检查 module-info.class 结构。如果 JAR 被混淆、签名损坏或用旧版 JDK 打包,JVM 可能静默跳过它,然后假装这个模块不存在。










