0

Ошибка NoSuchFieldError в Java

11

Вопрос: Ошибка NoSuchFieldError из-за несовместимого изменения класса

Я сталкиваюсь с ошибкой NoSuchFieldError в своем коде. Oracle не очень ясно объясняет, почему возникает эта ошибка, только указывая, что: «эта ошибка может возникать только во время выполнения, если определение класса несовместимо изменилось.»

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

Буду признателен за любые советы или разъяснения!

5 ответ(ов)

0

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

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

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

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

0

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

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

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

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

0

При отладке этих ошибок в интегрированной среде разработки (например, в Eclipse) следует остерегаться проблемы с зависимостями между проектами. Если вы используете разные версии библиотеки в различных проектах-зависимостях, загрузчик классов может выбрать неправильную версию. Это может произойти, если один проект зависит от JAR-файла, созданного из Eclipse-проекта, а также от самого проекта, из которого был сгенерирован JAR-файл. С устаревшими классами в JAR-файле могут быть загружены неактуальные версии классов из проекта.

Пример:

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

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

В класс project2 добавляется финальное статическое поле, после чего он перекомпилируется, но project2.jar не пересобирается.

При запуске project1 может возникнуть исключение, так как классы project2 могут быть загружены либо непосредственно из проекта, либо из JAR-файла, в котором поле отсутствует.

0

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

Например:

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, которая делает это за вас.

0

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

Я работаю над крупным проектом, в котором есть несколько файлов pom.xml, разбросанных по всему проекту. Один из моих коллег обновил номер версии одной из зависимостей, но не обновил каждое место, где эта зависимость использовалась, что привело к несовпадению библиотек в classpath.

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь