【问题标题】:How to let a java class on classpath access a class belonging to a module on module-path如何让类路径上的 java 类访问属于模块路径上的模块的类
【发布时间】:2019-10-30 16:15:58
【问题描述】:

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

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

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

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

基本上,

  1. moduleA 的modA.A 调用非模块化类automod.Foo 上的方法。 automod.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.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

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

【问题讨论】:

  • 如果需要,我可以附上以上所有类的代码。

标签: java module classpath module-path unnamed-module


【解决方案1】:

当您使用--module 命令启动Java 应用程序时,您传递的值是“根”模块。通过--add-modules 添加的模块也是如此。模块系统根据这些根模块确定整个模块图。换句话说,它读取module-info 文件,找到requires 指令,然后在模块路径中搜索那些需要的模块。它以传递方式执行此操作。一些模块还在服务上声明一个或多个uses 指令。 provides 任何这些服务的模块路径上的任何模块也将被加载,无论是否有任何模块 requires 它们。

这意味着如果模块路径中有一个模块不需要任何加载的模块并且不提供任何加载的模块所需的任何服务,则不会加载该模块。如果您有兴趣查看解析了哪些模块,可以使用以下命令:

java --show-module-resolution --dry-run -p [MODULEPATH] -m [MODULE]

在你的情况下,我只能假设你的其他模块都不需要modularX,所以当它在 modulepath 上时它不会被加载。但是,当它在 classpath 上时,事情的工作方式会有所不同,并且它会被类路径上的非模块化代码发现。不过,您仍然可以使用模块路径,只需确保您的 moduleX 模块已加载。这可以通过使用--add-modules 来强制:

java -p moduleA.jar;automod.jar;moduleX.jar --add-modules moduleX -cp nonmodular.jar -m moduleA/modA.A

请注意,您还可以通过--limit-modules 限制模块。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-23
    • 2020-04-14
    • 2021-09-23
    • 2018-05-02
    • 1970-01-01
    相关资源
    最近更新 更多