Как добавить ресурсы в две модульные банки в одноименных папках?

#java #java-9 #java-platform-module-system #java-17

Вопрос:

Предполагая, что у нас есть два файла jar с двумя разными модулями. Оба jar-файла содержат некоторые ресурсы (скажем, png-файлы) в папке под названием изображения в их jar. Когда я сейчас пытаюсь запустить модуль на java, я получаю следующую ошибку:

 Error occurred during initialization of boot layer
java.lang.LayerInstantiationException: Package images in both module A and module B
 

Хотя папка «Мои изображения» не предназначена для пакета, а представляет собой просто папку, содержащую ресурсы. Итак, как я могу поместить два модуля с папкой изображений в свой путь к модулю?

Комментарии:

1. Я вполне уверен, но не уверен, что способ, которым вы должны решить эту проблему, заключается в том, чтобы просто прояснить их: например foo.bar.images , foo.bazz.images И.

2. Правило заключается в том, что все, что выглядит как пакет, рассматривается как пакет, поэтому вы можете попробовать поместить файлы в МЕТА-информацию/изображения вместо этого. Не уверен, что это сработает, но легко попробовать.

3. До внедрения модульной системы поиск ресурсов, начиная с /images , мог непредсказуемо привести к произвольным результатам любого файла jar. Теперь модульная система сообщает вам, что есть проблема. Почему вы настаиваете на хранении ресурсов в путях с конфликтами имен?

4. Как писал Хольгер: разные модули, разные пакеты. Используйте SPI ServiceLoader для поиска нескольких реализаций служб, включая источники ресурсов во время выполнения. Возможности автоматического слияния пути к классу не работают в модульном мире.

Ответ №1:

Как добавить ресурсы в две модульные банки в одноименных папках?

Хотя это можно сделать, поместив ресурсы под путь, который не является допустимым именем пакета, например, META-INFO/resources или другой путь с - дефисом в нем, я бы посоветовал не делать этого, так как такие ресурсы не инкапсулированы и могут не быть однозначно идентифицируемыми с некоторыми API.

Другими словами: ЛЮБОЙ код в приложении может загрузить ресурс, который не находится внутри допустимого пакета, а не только код модуля в банке, содержащей ресурс.

А также: если ресурс не имеет уникального имени, основанного на его пути внутри jar, API может найти только один из ресурсов с таким же именем ClassLoader.findResource .


Мой совет состоял бы в том, чтобы создать в вашем модуле пакет с тем же именем , что и у модуля, с .images суффиксом. например mod.foo.images , а затем поместить ваши ресурсы в этот пакет. Затем загрузите ресурс с помощью модульного API загрузки ресурсов:

 MyClass.class.getModule().getResourceAsStream("mod/foo/images/my_image.jpg")
 

Таким образом, ресурс будет загружаться только кодом в том же модуле ( mod.foo при условии, что вы поместите его в путь к модулю), а также во избежание любой двусмысленности с именами ресурсов.