首页 > 解决方案 > 如何让类路径上的 java 类访问属于模块路径上的模块的类

问题描述

我正在尝试关于谁可以访问和什么的各种访问规则,我在模块系统文档的状态中看到了这个声明,

未命名的模块读取所有其他模块。因此,从类路径加载的任何类型的代码都可以访问所有其他可读模块的导出类型,默认情况下,这些模块将包括所有命名的内置平台模块。

因此,我编写了以下代码以使用以下结构对其进行测试:

moduleA/modA.A --> automod/automod.Foo --> nonmodular.Junk --> moduleX/modX.X

基本上,

  1. moduleAmodA.A调用非模块化类的方法automod.Fooautomod.Foo被包装成automod.jar并放在module-path. moduleA 的 module-info 有requires automod;子句。正如预期的那样,这工作正常。

  2. automod.Foo调用nonmodular.Junk类上的方法。nonmodular.Junk被包装成nonmodular.jar并穿上classpath。正如预期的那样,这工作正常。

  3. nonmodular.Junk调用 moduleX 上的方法modX.XmodX.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

知道为什么吗?从类路径加载的任何类都应该能够访问模块导出的任何类。

标签: javamoduleclasspathmodule-pathunnamed-module

解决方案


当您使用该--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.


推荐阅读