Используйте java buildloader build с использованием jdk8 в> = java9 - PullRequest
2 голосов
/ 30 марта 2020

У меня есть две банки. Один предоставляет интерфейсы служб и класс загрузки служб, а другой - реализацию этой службы.

Это прекрасно работает при запуске этого в jdk8, но я получаю ошибку service type not accessible to unnamed module @3754a4bf при запуске в jdk9 или новее.

Я перенес эти два jar-файла в базовый jar-модуль, и это прекрасно работает при работе на> = jdk9, но это не работает на jdk8 из-за неправильной версии файла класса.

Итак, я у меня нет проблем с использованием java serivceloader api с java 8 или 9.

Мне известно о https://blog.codefx.org/tools/multi-release-jars-multiple-java-versions/, но я хочу избежать процесса сборки более сложный Сборка уже включает в себя перемещение классов и другие вещи.

Мой вопрос: есть ли способ использовать те же самые jar-файлы, работающие на jdk8 и> = jdk9, используя java api службы загрузки?

1 Ответ

3 голосов
/ 30 марта 2020

В JDK9 и выше все банки являются «модулями». Если у них нет есть определение модуля (которое вы создаете, создав файл с именем module-info.java и помещая объявление модуля внутри), его имя - «безымянный модуль @whwhat», он экспортирует все свои пакеты, и может получить доступ ко всему, экспортированному любым другим модулем (в модуле-говорит: он «читает» все). Это означает, что если all ваши зависимости classpath являются такими безымянными модулями, они все экспортируют все, и все они читают все, таким образом, все они могут получить доступ к чему-либо, помеченному public, от кого-либо еще - как это работает в JDK8, и таким образом, почему все это совместимо.

Чтобы было понятно: в JDK9 для кода в модуле (jar) A для доступа к методу, классу или полю из модуля (jar) B, затем в дополнение к обычному модификаторы доступа (ключевое слово public), B необходимо «экспортировать» этот пакет, а A должен прочитать этот модуль, иначе он не работает. Если вы явно не пишете файлы информации о модуле для какой-либо из сторон, ну, тогда вы получаете поведение по умолчанию: «экспортировать все» и «читать все», что возвращает нас к сценарию JDK8: вещь должна быть отмечена public, и тогда вы можете получить к нему доступ.

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

Ошибка означает, что «тип сервиса» [1] не «доступен» [2] для «неназванного модуля» @ 3754a4bf "[3]. Давайте разберем это на части:

[1] загрузчик сервисов работает, определяя интерфейс, который реализует «сервис-провайдер», и класс, использующий загрузчик сервисов, затем заканчивается кучей экземпляров этого интерфейса; каждый представляет одну реализацию. Это Foo в ServiceLoader.load(Foo.class).

[2], «доступный» для модуля, говорит: либо код, которому это необходимо, явно не «читал» его, либо код, который его не экспортировал it.

[3] 'неназванное module@3754abf' - это имя модуля, который пытается получить к нему доступ.

Взяв все это вместе, это означает: вы работаете под ложным предположения: Что бы ни содержал jar в вашем интерфейсе сервиса (о котором я говорил * 1026), это NOT неназванный модуль или, возможно, не опубликован c. Обратите внимание, что если это интерфейс publi c внутри класса not-publi c (то есть: /* package private */ class Example { public interface MyServiceInterface {} }), то он, вероятно, все еще считается «не опубликован c достаточно».

Если это именованный модуль (что означает: у него есть файл module-info.java), затем экспортируйте пакет, в котором находится интерфейс службы. См. любое руководство (название системы модулей java) о том, как это настроить. Если это не так, убедитесь, что это интерфейс publi c или абстрактный класс, а если он внутри какого-то другого типа, убедитесь, что это тоже publi c. Если это не так, проверьте ваши пути к классам; javac довольно непреклонен, что один из этих двух случай.

...