Миграция JDK11: ошибка компиляции показана в Eclipse 2018-12, но код работает нормально - PullRequest
0 голосов
/ 23 января 2019

При переходе с Oracle JDK 8 на Откройте JDK 11.0.1 с использованием Eclipse 2018-12 Я, очевидно, обнаружил еще одну ошибку, связанную с JPMS, которая затрудняет работать с внешними немодулированными .jar's в рамках модульного проекта Java. Я отследил свою проблему до полного примера ниже.

Пример был получен из процесса миграции реального проекта (с использованием все еще немодулированного javax.servlet.api ), который вызвал некоторые головные боли. Он состоит из четырех проектов maven M, N, Y и X , составляющих по одному Java-модулю каждый, и другого проекта Maven, который составляет немодулярный проект Java W . Я использую maven и maven-compiler-plugin 3.8.0 . Мои наблюдения:

  • Eclipse показывает ошибки в M.java , но работает класс M с параметрами по умолчанию, работает без ошибок
  • если я включу артефакт w в качестве дополнительной зависимости maven в проекте M , ошибки останутся
  • если я переименую проект Y в проект O вместе с артефактом, именем пакета и информацией о модуле, ошибки не отображаются
  • если удалить , требуется w в модуле m , ошибки не отображаются
  • если я сделаю проект W модульным, добавив module-info.java , ошибки не будут отображаться
  • если я сделаю проект W модульным, добавив Automatic-Module-Name: w in MANIFEST.MF , ошибка останется

Очевидно, что повторное объявление автоматических модулей, таких как module w в проектах верхнего уровня , похоже, вызывает проблемы со встроенным компилятором Eclipse и не позволяет нам правильно работать с Затмение (тогда как запуск проекта работает хорошо). На мой взгляд, это несоответствие является еще одной ошибкой в ​​Eclipse 2018-12 (наряду с проблемами, которые я описал в Автоматические модули не найдены в Eclipse 2018-12 при открытии проекта и Java-модуль не найден в время выполнения даже с требует переходного ).

Мой вопрос: кто-то может подтвердить это как ошибку, или это уже известно? Для нас это полный пробный показ, поскольку наш проект зависит от разных библиотек, которые не являются ни модульными, ни имеют атрибут Automatic-Module-Name . И пока существует ошибка Eclipse, описанная в этом посте, мы не сможем перейти на JDK 11.

Sidemark : мы не хотим настраивать наши проекты после извлечения из SCM, чтобы запустить его в Eclipse. Для нас это было не нужно до сих пор (, и это действительно здорово при работе с Maven и Eclipse, спасибо всем, кто сделал это возможным до сих пор! ), и я с трудом избегаю ручной настройки модуля пути наших проектов затмения или запуска конфигураций.


Итак, вот полный и воспроизводимый пример:

Проект M (модульный)

// M.java
package m;
import com.example.n.N;
public class M {
    public static void main(String[] args) {
        System.out.println("M");
        N.main(null);
    }
}

// module-info.java
open module m {
    requires n;
    requires w;
}

// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mavenexample2</groupId>
  <artifactId>m</artifactId>
  <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency> 
          <groupId>com.mavenexample2</groupId>
          <artifactId>n</artifactId>
          <version>0.0.1-SNAPSHOT</version>         
        </dependency>

        <dependency>
          <groupId>com.mavenexample2</groupId>
          <artifactId>y</artifactId>
          <version>0.0.1-SNAPSHOT</version>             
        </dependency>
    </dependencies> 
</project>

Проект N (модульный)

// N.java
package com.example.n;
public class N {
    public static void main(String[] args) { 
        System.out.println("N");
    }
}

// module-info.java
open module n {
    exports com.example.n;
}

// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mavenexample2</groupId>
  <artifactId>n</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</project>

Проект Y (модульный)

// Y.java
package com.example.y;
public class Y {
    public static void main(String[] args) { 
        System.out.println("Y");
    }
}

// module-info.java
open module com.example.y {
    exports com.example.y;
    requires com.example.x;
}

// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mavenexample2</groupId>
  <artifactId>y</artifactId>
  <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.mavenexample2</groupId>
            <artifactId>x</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

Проект X (модульный)

// X.java
package com.example.x;
public class X {
    public static void main(String[] args) { 
        System.out.println("X");
    }
}

// module-info.java
open module com.example.x {
    exports com.example.x;
    requires w;
}

// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mavenexample2</groupId>
  <artifactId>x</artifactId>
  <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency> 
          <groupId>com.mavenexample2</groupId>
          <artifactId>w</artifactId>
          <version>0.0.1-SNAPSHOT</version>             
        </dependency>
    </dependencies>

</project>

Проект W (немодульный)

// W.java
package external;
public class W {
    public static void main(String[] args) { 
        System.out.println("W");
    }
}

// pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mavenexample2</groupId>
  <artifactId>w</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</project>

Пожалуйста, выполните Maven> Обновить проекты ...> все, чтобы получить все синхронизировано после определения проектов или изменения зависимостей вашего модуля. Кроме того, закройте также немодульный проект M после выполнения mvn clean install , так как в противном случае вы получите ошибку, описанную здесь: Автоматические модули не найдены в Eclipse 2018- 12 при открытии проекта .

1 Ответ

0 голосов
/ 30 января 2019

Действительно, в Eclipse была ошибка, которая появлялась только тогда, когда компиляция выполнялась в очень специфическом порядке.

Справочная информация: В эпоху JPMS пакет имеет различное содержимое в зависимости от того, какой модуль запрашивает.В этом примере разные модули видят разные конфигурации для пакета com.example: из некоторого pov он содержит дочерний пакет n, в других - нет.В целях повышения производительности каждый результат такого поиска кэшируется, что вызывает зависимость порядка: какой модуль первым просмотрел пакет com.example решил, какие вклады в пакет были известны.

Любопытно, что тот же JPMSчто делает разделенные пакеты незаконными, требует, чтобы компилятор рассматривал каждый родительский пакет с несколькими участвующими модулями как разделенный пакет, вызывая значительное увеличение сложности реализации.

(Отредактировано :) Ошибка исправлена ​​как Ошибка Eclipse 543765 , исправление доступно с выпуска 2019-03.

...