Ответ 1
Я смог воспроизвести ту же самую проблему с компиляцией в Eclipse (Mars, 4.5.1) и из командной строки с помощью Maven (версия плагина Maven Compiler 3.5.1 последний на данный момент).
- Компиляция и запуск main из Eclipse > Без ошибок
- Компиляция из консоли /Maven и запуск main из Eclipse > Ошибка
- Компиляция из консоли /Maven и запуск main через
exec:java
из консоли > Ошибка - Компиляция из Eclipse и запуск main через
exec:java
из консоли > Без ошибок -
Компилирование из командной строки непосредственно с помощью
javac
(без Eclipse, no Maven, jdk-8u73) и запуск из командной строки непосредственно с помощьюjava
> Ошибкаfoo Exception in thread "main" java.lang.IllegalAccessError: tried to access class com.sample.package1.Foo from class com.sample.package2.Main at com.sample.package2.Main.lambda$MR$main$getFoo$e8593739$1(Main.java:14) at com.sample.package2.Main$$Lambda$1/2055281021.apply(Unknown Source) at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source) at java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Unknown Source) at java.util.stream.AbstractPipeline.copyInto(Unknown Source) at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source) at java.util.stream.AbstractPipeline.evaluate(Unknown Source) at java.util.stream.ReferencePipeline.forEach(Unknown Source) at com.sample.package2.Main.main(Main.java:14)
Обратите внимание на вышеописанный стек, первый (pre-java-8) вызов работает отлично, а второй (основанный на java-8) генерирует исключение.
После некоторого расследования я нашел соответствующие ссылки:
-
отчет об ошибке JDK-8068152, описывающий подобную проблему и, прежде всего, упоминание о плагине Maven Compiler и Java:
Это похоже на проблему, вызванную предоставленным плагином maven. Предоставленный плагин maven (в каталоге "plugin" ) добавляет "tools.jar" к
ClassLoader.getSystemClassLoader()
, и это вызывает проблему. Я действительно не вижу многого, что могло бы (или должно) быть сделано на стороне джавака, извините.Более подробно
ToolProvider.getSystemJavaCompiler()
рассмотритClassLoader.getSystemClassLoader()
, чтобы найти классы javac. Если он не находит javac там, он пытается автоматически найти tools.jar и создаетURLClassLoader
для tools.jar, загружая javac с помощью этого загрузчика классов. Когда компиляция выполняется с использованием этого загрузчика классов, он загружает классы, используя этот загрузчик классов. Но тогда, когда плагины добавят tools.jar вClassLoader.getSystemClassLoader()
, классы начнут загружаться системным загрузчиком классов. И закрывается доступ к частному доступу при доступе к классу из одного пакета, но загружается другим загрузчиком классов, что приводит к вышеуказанной ошибке. Это усугубляется тем, что maven кэширует результатыToolProvider.getSystemJavaCompiler()
, благодаря которым запуск плагина между двумя компиляциями по-прежнему приводит к ошибке.(ПРИМЕЧАНИЕ: полужирный - мой)
-
Плагин Maven Compiler - Использование компиляторов Non-Javac, описывающий, как вы можете подключить другой компилятор к Maven Compiler Plugin и используйте его.
Итак, просто перейдем из следующей конфигурации:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
К следующему:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
</plugin>
Исправлена проблема, no IllegalAccessError
для того же кода. Но при этом мы фактически удалили разницу между Maven и Eclipse в этом контексте (делая Maven с помощью компилятора Eclipse), поэтому это был обычный результат.
Таким образом, это приводит к следующим выводам:
- В этом случае компилятор Eclipse Java отличается от Maven Java Compiler, ничего нового, но это еще одно подтверждение
- У компилятора Maven Java в этом случае есть проблема, в то время как у компилятора Eclipse Java нет. Компилятор Maven совместим с компилятором JDK. Таким образом, на самом деле это может быть ошибка JDK, влияющая на компилятор Maven.
- Создание Maven с использованием того же компилятора Eclipse устраняет проблему или скрывает ее.
Для справки, я пробовал также следующее без особого успеха, прежде чем переключиться на компилятор eclipse для Maven:
- Изменение версии плагина Maven Compiler, каждая версия от 2,5 до 3.5.1
- Попытка с JDK-8u25, JDK-8u60, JDK-8u73
- Убедитесь, что Eclipse и Maven Compiler используют тот же javac, явно используя параметр
executable
Подводя итог, JDK согласован с Maven, и это, скорее всего, ошибка. Ниже некоторых связанных сообщений об ошибках я обнаружил:
- JDK-8029707: IllegalAccessError с использованием метода унаследованного пользовательского вызова. Исправлено как "Не исправить" (это была точно такая же проблема).
- JDK-8141122: IllegalAccessException с использованием ссылки метода на пакет-частный класс через pub. Открыть (опять же, точно такая же проблема)
- JDK-8143647: Ссылка на метод компиляции Javac, которая позволяет результаты в IllegalAccessError. Исправлено в Java 9 (аналогичная проблема, код pre-java-8 будет работать нормально, код стиля java-8 сломается)
- JDK-8138667: java.lang.IllegalAccessError: попытался получить доступ к методу (для защищенный метод). Open (аналогичная проблема, компиляция отлично, но не ошибка времени выполнения для незаконного доступа к лямбда-коду).