Подтвердить что ты не робот

NoSuchFieldError Java

Я получаю NoSuchFieldError в своем коде, теперь оракул не очень-то разбирается в том, почему эта ошибка возникает только из-за того, что эта ошибка может возникать только во время выполнения, если определение класса несовместимо изменилось.

Может кто-нибудь объяснить мне, как можно "несовместимо изменить" класс? Класс, о котором я говорю, расширяет довольно много классов, поэтому я подозреваю, что это может быть связано с этим, но я не знаю, с чего начать искать или что я ищу.

4b9b3361

Ответ 1

Эта ошибка обычно возникает, если вы только частично перекомпилируете свой код. У вас есть старый код, который ссылается на поле, которое больше не существует в файлах с перекомпилированным классом.

Решение состоит в том, чтобы очистить все файлы классов и скомпилировать все из свежих.

Обновление: Если вы все еще получаете такую ​​же ошибку после перекомпиляции всего, то вы, вероятно, компилируете ее из одной версии внешней библиотеки и используете другую во время выполнения.

Теперь вам нужно сначала определить класс, который вызывает проблему (похоже, что вы это уже сделали), а затем запустите приложение с помощью командной строки -verbose:class. Он выгрузит много информации о загрузке классов на ваш стандарт, и вы сможете узнать, от чего загружен проблемный класс.

Ответ 2

Когда компилятор скомпилировал код, который выбрасывает ошибку, появился еще один класс с полем, и ваш класс мог получить доступ к этому полю (считывая или изменяя значение).

В среде выполнения другой класс каким-то образом не имеет поля с этим именем, что приводит к указанной ошибке.

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

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

Ответ 3

Что-то, чтобы быть осторожным при отслеживании этих ошибок в среде IDE (Eclipse в моем случае), - это следить за зависимостями проектов, от которых может зависеть ваш проект. Если вы используете разные версии библиотеки в разных зависимых проектах, загрузчик classpath может забрать неправильный. Это включает в себя проект, зависящий от банки, созданной из проекта Eclipse, и имеющий другой проект, зависящий от этого проекта и проекта, из которого была создана банка. Устаревшие классы в банке потенциально могут быть загружены вместо классов из проекта.

Пример:

project1 зависит от project2 и project3

project3 зависит от project2.jar, jar, сгенерированного из файлов классов в project2

Конечное статическое поле добавляется к классу в project2, который перекомпилируется, а project2.jar не перестраивается

Запуск project1 может вызвать исключение, так как классы из project2 могут быть загружены непосредственно из проекта или в банку, у которой нет поля

Ответ 4

Это означает, что вы, вероятно, перекомпилировали класс, на который зависел другой уже скомпилированный класс, и не перекомпилировали соответствующий класс.

Например:

public class MyClass {
    public int num;
    public MyClass() { num = 1; }
}

public class MyDependingClass {
    private int foo;
    public MyDependingClass(MyClass init) {
        foo = init.num;
    }
}

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

И это сработало.

Позже вы решите реорганизовать MyClass:

public class MyClass {
    private int innernum;
    public int getNum() {
        return innernum;
    }
    public MyClass() { innernum = 1; }
}

Если вы компилируете MyClass, а не MyDependingClass, когда вы запускаете свою программу и создаете экземпляр MyDependingClass, вы получите свой NoSuchFieldError.

Кратковременное исправление, вероятно, состоит в том, чтобы перекомпилировать все классы в вашей рабочей области, что должно показать ошибку.

Долгосрочное исправление заключается в использовании Eclipse или NetBeans или другой среды IDE, которая обрабатывает это для вас.

Ответ 5

Это было довольно сложно для меня, поэтому я пишу свое решение.

Я работал в IntelliJ с Boot, все было хорошо, все версии Java 8 были настроены соответствующим образом.

Через несколько часов я каким-то образом проверил на терминале javac -version и угадаю, что он был установлен на версию 9. Так что обязательно поищите javac, я знаю его нелогично, но предположительно, так как я установил jdk на профиле bash, на IntelliJ и т.д., Я не должен был беспокоиться об этом.

Надеюсь, поможет!

Ответ 6

Поймите эту ошибку:

Это ошибка java.lang.LinkageError которая возникает, когда jvm пытается связать загруженные классы. Обратите внимание, что код сначала компилируется (с зависимыми классами), затем все задействованные классы загружаются jvm, а затем эти классы связываются вместе.

Подумайте об ошибке: NoSuchField, это означает, что при связывании целевого класса поле не существует. Но при компиляции класс должен иметь это поле, иначе код не сможет скомпилироваться. При подключении jvm обнаруживает, что этого поля нет. Таким образом, единственная причина в том, что мы компилируем с классом с этим полем, а другая версия этого класса (у которого нет этого поля) загружается и связывается.


Решите вашу ситуацию между двумя распространенными причинами этой ошибки

Обычно неправильно загруженный класс - это либо измененный исходный код, либо класс в одном из ваших зависимых пакетов jar. Мы можем решить эту -verbose:class найдя неправильно загруженный класс, добавив -verbose:class в jvm, который пытается запустить ваше приложение, в соответствии с вашими идеями. Этот аргумент выводит все загруженные классы в консоль. В eclipse мы помещаем его в: щелкните правой кнопкой мыши на project-> run as-> run configrations-> arguments tag-> поле VM arguement.

После того, как вы найдете неправильно загруженный класс, обычно это либо класс, в котором у вас есть исходный код в вашем проекте, либо он находится в пакете jar, от которого зависит ваш проект. Разная ситуация приводит к разным решениям.


Решение для случая с исходным кодом:

Скорее всего, вы изменили этот класс (добавив поле в исходный код), но не перекомпилировали его. Это может произойти по разным причинам, но вы должны удалить скомпилированный файл старой версии .class этого класса и перекомпилировать его, чтобы файл новой версии .class содержал это поле.


Решение для кейса

Вы должны попытаться позволить проекту загрузить правильный пакет jar. Но почему другая версия используется, обычно потому, что они оба зависят (от разных частей вашего проекта). Ситуация очень проста (и может не существовать в реальном проекте), если вы пишете коды, которые напрямую зависят от них обоих, просто выберите один и отбросьте другой.

Но есть вероятность, что ваш код косвенно зависит от них. И вы не хотите менять свой код (или менять как можно меньше).

Одним из решений является то, что вы пишете свой собственный ClassLoader для ClassLoader с обоими: возможно ли использовать два Java-класса с одинаковым именем и одним и тем же пакетом? (Я не пробовал это)

Если вы решите загрузить правильную версию (содержащую такое field), и ваш код, который косвенно зависит от wrong версии, все еще может работать (надеюсь), то у нас есть гораздо более простое решение: пусть ваш проект выберет правильную версию.

Например, затмение. Вы можете использовать тег " Order and Export в свойстве " Java Build Path, просто измените порядок, чтобы позволить правильной версии опередить wrong версию, поскольку функция части " Order такова:

С одной стороны, он действует как порядок разрешения для ресурсов, используемых при создании рассматриваемого проекта (часть "Заказ").

Если правильная версия или неправильная версия там не отображаются, вы должны определить, какой пакет зависит от него, и скорректировать его порядок, благодаря функции " Export часть". Прочитайте вкладку "Заказ и экспорт" в "Пути сборки Java" для получения подробной информации.

Ответ 7

Хотя основная причина та же, что описана в верхних ответах, моя проблема немного отличалась от других ответов, которые я нашел здесь, поэтому я решил поделиться.

Я работаю над большим проектом, в котором по всему проекту разбросано несколько мавенов. Коллега обновил номер версии одной из зависимостей, не обновляя каждое место, где появилась эта зависимость, что привело к несовпадению библиотек в пути к классам.

Решение состояло в том, чтобы обновлять каждое вхождение этой зависимости, чтобы иметь тот же номер версии. В качестве примечания, чтобы предотвратить повторение этого, мы добавили туда переменную, и теперь мы контролируем номер версии этих зависимостей из одного места.