java - 如何让类路径上的 java 类访问属于模块路径上的模块的类
问题描述
我正在尝试关于谁可以访问和什么的各种访问规则,我在模块系统文档的状态中看到了这个声明,
未命名的模块读取所有其他模块。因此,从类路径加载的任何类型的代码都可以访问所有其他可读模块的导出类型,默认情况下,这些模块将包括所有命名的内置平台模块。
因此,我编写了以下代码以使用以下结构对其进行测试:
moduleA/modA.A --> automod/automod.Foo --> nonmodular.Junk --> moduleX/modX.X
基本上,
moduleA
modA.A
调用非模块化类的方法automod.Foo
。automod.Foo
被包装成automod.jar
并放在module-path
. moduleA 的 module-info 有requires automod;
子句。正如预期的那样,这工作正常。automod.Foo
调用nonmodular.Junk
类上的方法。nonmodular.Junk
被包装成nonmodular.jar
并穿上classpath
。正如预期的那样,这工作正常。nonmodular.Junk
调用 moduleX 上的方法modX.X
。modX.X
被打包成moduleX.jar
. 就是这一步有问题。如果我将 moduleX.jar 放在类路径上,但如果我将 moduleX.jar 放在模块路径上,它就可以工作。(moduleX 的模块信息确实有exports modX;
子句。)
换句话说,以下命令有效:
java --module-path moduleA.jar;automod.jar; -classpath nonmodular.jar;moduleX.jar --module moduleA/modA.A
使用以下输出:
In modA.A.main() Calling automod.Foo()
In automod.Foo()
In modA.A.main() Calling automod.foo.main()
In automod.Foo.main() Calling nonmodular.Junk()
In automod.Foo.main() Calling nonmodular.Junk.main()
In nonmodular.Junk.main calling new modX.X()
In modX.X()
但以下命令不起作用:
java --module-path moduleA.jar;automod.jar;moduleX.jar -classpath nonmodular.jar; --module moduleA/modA.A
这是输出:
In modA.A.main() Calling automod.Foo()
In automod.Foo()
In modA.A.main() Calling automod.foo.main()
In automod.Foo.main() Calling nonmodular.Junk()
In automod.Foo.main() Calling nonmodular.Junk.main()
In nonmodular.Junk.main calling new modX.X()
Exception in thread "main" java.lang.NoClassDefFoundError: modX/X
at nonmodular.Junk.main(Junk.java:5)
at automod/automod.Foo.main(Foo.java:10)
at moduleA/modA.A.main(A.java:10)
Caused by: java.lang.ClassNotFoundException: modX.X
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 3 more
知道为什么吗?从类路径加载的任何类都应该能够访问模块导出的任何类。
解决方案
当您使用该--module
命令启动 Java 应用程序时,您传递的值是“根”模块。通过添加的模块也是如此--add-modules
。模块系统根据这些根模块确定整个模块图。换句话说,它读取module-info
文件,找到requires
指令,然后在模块路径中搜索那些需要的模块。它以传递方式执行此操作。一些模块还在uses
服务上声明一个或多个指令。provides
也将加载任何这些服务的模块路径上的任何模块,无论requires
它们是否有任何模块。
这意味着如果模块路径上有一个模块不需要任何加载的模块并且不提供任何加载的模块所需的任何服务,则不会加载该模块。如果您有兴趣查看解决了哪些模块,可以使用以下命令:
java --show-module-resolution --dry-run -p [MODULEPATH] -m [MODULE]
在你的情况下,我只能假设你的其他模块都不需要modularX
,所以当它在模块路径上时它不会被加载。但是,当它在类路径上时,事情的工作方式会有所不同,并且它是由也在类路径上的非模块化代码发现的。不过,您仍然可以使用模块路径,只需确保您的moduleX
模块已加载。这可以通过使用来强制--add-modules
:
java -p moduleA.jar;automod.jar;moduleX.jar --add-modules moduleX -cp nonmodular.jar -m moduleA/modA.A
请注意,您还可以通过--limit-modules
.
推荐阅读
- dataset - 是否有任何现有的数据集可用于光学字符识别?
- java - 带有 Sql Server Express 2008 的 Java 休眠
- mongodb - Java 项目中的 MongoDB + Spark。无法使用数据集
- sql - 加入数据可能不匹配的两组数据
- python - 鸢尾花数据集的多类分类
- javascript - 使用 react-bootstrap 未显示模态
- odoo - 未使用不同类型触发的更改
- math - 使用角度值将 2D 矢量转换为 3D
- odata - 如何使用类似于 JSON 格式的 Avro 的 oData 接口选项来公开数据
- python - 基于排除关系中的项目的 Sqlalchemy 查询