Как позволить java-классу на classpath получить доступ к классу, принадлежащему модулю на module-path - PullRequest
0 голосов
/ 17 июня 2019

Я пробую различные правила доступа о том, кто может получить доступ и что, и я видел это утверждение в документе Состояние системы модулей,

Неименованный модуль читает все остальные модули.Таким образом, код любого типа, загруженный из пути к классу, сможет получить доступ к экспортируемым типам всех других читаемых модулей, которые по умолчанию будут включать все именованные встроенные модули платформы.

ИтакЯ написал следующий код, чтобы протестировать его со следующей структурой:

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

По сути,

  1. moduleA modA.A вызывает метод на немодулярном модулекласс automod.Foo.automod.Foo упакован в automod.jar и надет module-path.Информация о модуле для модуля A содержит предложение requires automod;.Это работает нормально, как и ожидалось.

  2. automod.Foo вызывает метод класса nonmodular.Junk.nonmodular.Junk упакован в nonmodular.jar и надет classpath.Это работает нормально, как и ожидалось.

  3. nonmodular.Junk вызывает метод для модуля X modX.X.modX.X упакован в moduleX.jar.Именно этот шаг имеет проблему.Это работает, если я помещаю moduleX.jar в classpath, но не если я помещаю moduleX.jar в module-path.(Информация о модуле для модуля X имеет 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

Есть идеи почему?Любой класс, загруженный из пути к классам, должен иметь доступ к любым классам, экспортируемым модулем.

1 Ответ

1 голос
/ 17 июня 2019

Когда вы запускаете приложение Java с помощью команды --module, передаваемое значение является «корневым» модулем. То же самое относится и к модулям, добавленным через --add-modules. Система модулей определяет весь граф модулей из этих корневых модулей. Другими словами, он читает файл module-info, находит директивы requires и затем ищет путь к модулю для этих требуемых модулей. Это делает это транзитивно. Некоторые модули также объявляют одну или несколько директив uses для службы. Любые модули на модульном пути, которые provides любой из этих служб также будут загружены, независимо от того, есть ли у любого модуля requires их.

Это означает, что если на модульном пути есть модуль, который не требуется ни одному загруженному модулю и не предоставляет никаких услуг, необходимых любому загруженному модулю, то указанный модуль не будет загружен. Если вам интересно узнать, какие модули разрешены, вы можете использовать следующую команду:

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

В вашем случае я могу только предположить, что ни один из ваших других модулей не требует modularX, поэтому, когда он находится на modulepath , он не загружается. Однако, когда он находится в classpath , все работает по-другому, и это обнаруживается вашим немодулярным кодом, который также находится в classpath. Вы все еще можете использовать modulepath, просто убедитесь, что ваш модуль moduleX загружен. Это может быть вызвано с помощью --add-modules:

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

Обратите внимание, что вы также можете ограничить модули с помощью --limit-modules.

...