Java11中运行类与运行模块的区别及类路径运行失败原因求解
Java 11模块系统问题解答
你的认知误区说明
你对unnamed module权限的理解本身是正确的:类路径下的非模块化Jar归属的unnamed module,确实可以访问所有已被JVM解析加载到运行时模块图的模块的导出包。
你存在的误区是:默认认为放在模块路径下的Jar会被JVM自动加载,实际上模块路径下的模块只有被纳入模块解析范围才会被加载,不会因为存在于模块路径就自动生效。
第一种运行方式失败的根本原因
你使用的java -classpath A.jar --module-path B.jar com.AMainClass属于类路径启动模式,这种模式下:
- JVM的模块系统默认的根模块只有
java.base,只会解析java.base以及它的依赖链内的模块 - 你放在模块路径的B.jar没有被纳入解析范围,JVM根本不会加载B模块,所以A.jar里引用B模块的代码自然会抛出类找不到的异常
如果要让这种模式运行成功,只需要显式指定把B模块加入解析范围即可:
java -classpath A.jar --module-path B.jar --add-modules <B的模块名> com.AMainClass
运行类和运行模块的核心区别
- 运行类(指定全限定主类启动的模式):
- 是兼容Java 8及更早版本的兼容模式,默认以类路径加载逻辑优先
- 模块系统默认根模块仅为
java.base,模块路径下的其他模块不会被自动解析,必须通过--add-modules显式指定才会被加载
- 运行模块(通过
--module指定启动模块的模式):- 是Java 9及以后版本的模块原生启动模式
- 你指定的启动模块会被作为根模块,JVM会自动递归解析根模块的所有依赖,把依赖链上的所有模块都加载到运行时模块图
- 你把非模块化的A.jar放在模块路径下会被识别为自动模块,自动模块默认声明对所有其他模块的依赖,所以JVM解析A模块时会自动加载模块路径下的B模块,无需额外配置就能正常运行
内容的提问来源于stack exchange,提问作者user16038501
相关产品推荐
相关产品推荐

