Eclipse не может найти классы, связанные с XML, после переключения пути сборки на JDK 10

Я работаю над проектом Maven (branch platform-bom_brussels-sr7) в Eclipse. Когда я недавно попытался переключить путь сборки Java для проекта на JDK 10, сборка Eclipse больше не может найти классы, такие как javax.xml.xpath.XPath, org.w3c.dom.Document или org.xml.sax.SAXException. Похоже, что xml-apis-1.4.01 только связанные с XML классы, в основном из зависимости Maven xml-apis-1.4.01.

Попытка сборки Maven из Eclipse работает без ошибок. Ctrl-LeftClick на одном из предположительно отсутствующих классов находит класс и открывает его в редакторе Eclipse. Похоже, что только сборка Eclipse затронута.

Я попробовал несколько вещей, но ничего не помогло. Я старался:

  • Проект Чистый
  • Различные версии Eclipse: кислород и фотон.
  • Сам Eclipse работает с JDK 8 и JDK 10.
  • Изменение уровня соответствия компилятора для проекта. Он строится с уровнем соответствия 8 и 10 по пути сборки JDK 8 и завершается неудачно для обоих с JDK 10 в пути сборки.

Ответ 1

Я предполагаю, что проект, переносимый с Java 1.8, все еще не имеет module-info.java. Это означает, что вы компилируете код в "неназванном модуле".

Код в безымянном модуле "читает" все наблюдаемые именованные и безымянные модули, в частности, он читает модуль "java.xml" из системной библиотеки JRE. Этот модуль экспортирует пакет как java.xml.xpath.

Кроме того, у вас есть xml-apis.java на пути к классам, который добавляет другой набор пакетов с такими же именами (java.xml.xpath и друзья). Говорят, что они связаны с неназванным модулем, как ваш собственный код.

Эта ситуация нарушает требование "уникальной видимости", как определено в JLS §7.4.3 (последний абзац). В частности, каждое квалифицированное имя типа Q.Id(JSL §6.5.5.2) требует, чтобы его префикс Q был уникально видимым пакетом (для простоты я игнорирую случай вложенных типов). Ergo: программа запрещена и должна быть отклонена компиляторами.

Это оставляет нам один вопрос и два решения:

(1) Вопрос: почему javac принимает программу?

(2) Решение: если вы добавите module-info.java в свой проект, вы можете через требуется контролировать, какой модуль читает ваш проект: requires java.xml; или requires xml.apis; (где "xml.apis" - это автоматический имя модуля "xml-apis-1.4.01.jar).

(3) Решение: если не превратить ваш проект в модуль, вы все равно сможете избежать конфликта, исключив java.xml из набора наблюдаемых модулей. В командной строке это будет сделано с помощью --limit-modules. Эквивалентом в Eclipse является диалоговое окно "Сведения о модульности", см. также JDT 4.8 Новое и заслуживающее внимания (см. вкладку Содержание). Поскольку java.xml неявно требуется через множество других наблюдаемых по умолчанию модулей, может быть хорошей идеей подтолкнуть все, кроме java.base, справа ("явно включенные модули") влево ("доступные модули") (и выборочно добавляйте те модули, которые нужны вашему проекту).

PS: Eclipse по-прежнему не предоставляет идеального сообщения об ошибке, вместо "не может быть разрешено" оно должно фактически сказать: "Пакет javax.xml.xpath доступен из более чем одного модуля: javax.xml, & lt; unnamed>.

PPS: Также странно: почему изменение порядка между JRE и jar на пути к классам (такое упорядочение не поддерживается ни Javac, ни JEP 261) меняет поведение компилятора.

Редактирует:

  • Алекс Бакли подтвердил, что данная ситуация незаконна, несмотря на то, что говорит Джавак. Ошибка в javac была поднята как JDK-8215739. Эта ошибка была подтверждена за несколько месяцев до выпуска Java 12. По состоянию на 2019-06 гг. Было решено, что Java 13 будет поставляться без исправления.
  • Сообщение об ошибке Eclipse было улучшено, чтобы упомянуть реальную проблему.
  • В Eclipse 2019-06 пользовательский интерфейс, используемый для Solution (3), был обновлен. Актуальную документацию можно найти в онлайн-справке.

Ответ 2

Похоже, это было сообщено как Eclipse Bug 536928. Возможно, если бы все проголосовали за это, они бы повысили приоритет.

Ответ 3

Видели что-то очень похожее в Eclipse 4.8.0 и JDK 10. Например

import org.w3c.dom.Element;

не удалось скомпилировать в Eclipse с: The import org.w3c.dom.Element cannot be resolved

Тем не менее, нажав F3 (Открытое объявление) для этого импорта, Eclipse смог открыть определение интерфейса - в данном случае в xml-apis-1.4.01.jar.

Тем временем сборки из Maven direct работали нормально.

В этом случае исправление должно было удалить эту зависимость из pom.xml:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.4.01</version>
    </dependency>

Тогда ошибки компиляции в Eclipse растаяли. После F3 снова появился интерфейс Element - теперь под модулем java.xml, под Системной библиотекой JRE под проектом. Также сборка Maven осталась в порядке.

Это похоже на проблему с разрешением Eclipse класса, который он находит и в модуле JDK, и в зависимом файле.jar.

Интересно, что в отдельной среде, на этот раз под Eclipse 4.9.0 и JDK 11, все в порядке, с зависимостью xml-apis:1.4.01 или без xml-apis:1.4.01.

Ответ 4

jdk 9+ внесли изменения, связанные с проектными головоломками. JDK был разбит на различные модули, а некоторые модули, javaee, jaxb и связанные с xml, больше не загружаются по умолчанию. Вы должны добавить их в свою maven-сборку напрямую, вместо того, чтобы ожидать, что они будут в jre classpath. см. этот вопрос

Ответ 5

Это скорее обходной путь, но, по моему опыту, его можно решить, перейдя на "Путь сборки Java", вкладку "Заказ и экспорт" и отправив "Зависимости Maven" внизу (так, чтобы он находился под "Системная библиотека JRE").