← Назад к вопросам

Что будешь делать, если при запуске проекта все появляется MissingMethodException

1.0 Junior🔥 91 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отладка MissingMethodException при запуске проекта

MissingMethodException обычно означает: метод, который вызывается в runtime, не найден в classpath.

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

Дифференциация: какой MissingMethodException?

Случай 1: NoSuchMethodException

public class Main {
    public static void main(String[] args) throws Exception {
        String obj = "Hello";
        // Пытаемся вызвать метод который не существует
        obj.getClass()
            .getDeclaredMethod("nonExistentMethod")  // ОПА!
            .invoke(obj);
    }
}

// Ошибка:
java.lang.NoSuchMethodException: java.lang.String.nonExistentMethod()

Случай 2: NoSuchMethodError

Это когда метод существовал в compile time, но пропал в runtime:

// ClassA.java (версия 1)
public class ClassA {
    public void oldMethod() { }
}

// Main.java (скомпилирован против версии 1)
public class Main {
    public static void main(String[] args) {
        ClassA a = new ClassA();
        a.oldMethod();  // Компилятор знает что метод существует
    }
}

// ClassA.java (версия 2 — в runtime используется эта версия)
public class ClassA {
    // oldMethod() удалили!
    public void newMethod() { }
}

// Runtime error:
java.lang.NoSuchMethodError: ClassA.oldMethod()V

Этот случай самый коварный потому что компилятор не ловит ошибку.

Мой систематический подход к отладке

Шаг 1: Читаю полный stack trace

Я ВСЕГДА читаю полный stack trace, не только первую строку:

java.lang.NoSuchMethodError: org.hibernate.Session.createQuery(Ljava/lang/String;)
    at com.myapp.dao.UserDao.findAll(UserDao.java:15)
    at com.myapp.service.UserService.getAllUsers(UserService.java:20)
    at com.myapp.api.UserController.getUsers(UserController.java:10)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

Это говорит: в UserDao.java:15 вызывается Session.createQuery(String), но она не существует.

Шаг 2: Проверяю версии dependency

Обычно это проблема версий:

# Проверяю версии в pom.xml
grep -A5 '<hibernate-core>' pom.xml

# Или через Maven
mvn dependency:tree | grep hibernate
mvn help:describe -Dartifact=org.hibernate:hibernate-core

Вывод может показать:

org.hibernate:hibernate-core:jar:4.3.11.Final:compile

Я гугл что-то в стиле: "Hibernate 4.3 Session.createQuery() signature"

И узнаю: в Hibernate 5.2 сигнатура изменилась!

Шаг 3: Проверяю конфликты версий

# Показывает граф зависимостей
mvn dependency:tree

# Может вывести что-то вроде:
[INFO] +- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.4.0:compile
[INFO] |  +- org.hibernate:hibernate-core:jar:5.4.25.Final:compile
[INFO] |  \- org.hibernate:hibernate-commons-annotations:jar:5.1.2.Final:compile
[INFO] +- org.hibernate:hibernate-core:jar:4.3.11.Final:compile  // КОНФЛИКТ!

Две разные версии одного jar'а в classpath!

Шаг 4: Проверяю что на диске (в классах)

# Распакую jar и посмотрю на метод
jar tf ~/.m2/repository/org/hibernate/hibernate-core/5.4.25.Final/hibernate-core-5.4.25.Final.jar | grep Session

# Или более прямо: смотрю classfile с помощью javap
javap -cp ~/.m2/repository/org/hibernate/hibernate-core/5.4.25.Final/hibernate-core-5.4.25.Final.jar org.hibernate.Session | grep createQuery

# Вывод:
// public <R> TypedQuery<R> createQuery(String qlString, Class<R> resultClass);
// public Query createQuery(String qlString);

Шаг 5: Проверяю что я вызываю

// Мой код
Session session = sessionFactory.openSession();
Query query = session.createQuery("SELECT u FROM User u");  // Какая версия метода?

Я проверяю в IDE: CTRL+Click на createQuery, и вижу какая версия используется во время компиляции.

Кейсы которые встречались

Кейс 1: Конфликт Hibernate версий

<!-- pom.xml —ошибка -->
<dependencies>
    <!-- Spring Boot bring в Hibernate 5.4 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>2.4.0</version>
    </dependency>
    
    <!-- А потом кто-то добавил старую версию явно -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.11.Final</version>  <!-- ОШИБКА! -->
    </dependency>
</dependencies>

Решение:

<!-- Удалить explicit dependency на старую версию -->
<!-- Или если нужна конкретная версия -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.4.25.Final</version>
</dependency>

<!-- Или лучше: управляй через spring-boot-dependencies BOM -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.4.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Потом:

mvn clean install
# Перекомпилируй

Кейс 2: Обновили library, забыли обновить код

// Старый API (Jackson 1.x)
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(object);

// Но обновили на Jackson 2.x где метод переименован
// На Jackson 2.x это работает, но если в classpath old версия...

Решение: обновить код под новую версию.

Кейс 3: Несовместимость между разными компонентами

Spring Boot 2.7.0
  ↓
  Requires Hibernate 5.6.x
  ↓
  Requires HikariCP 4.0.x
  ↓
  Requires PostgreSQL driver 42.3.x

Но developer добавил PostgreSQL driver 41.x
  ↓
  MissingMethodError: некий метод отсутствует

Решение: используй spring-boot-dependencies BOM для правильных версий.

Кейс 4: Проблема с class loaders

В application servers (Tomcat, JBoss) могут быть проблемы:

APP A: использует commons-lang 2.5
APP B: использует commons-lang 3.0

Оба приложения на одном Tomcat'е
↓
Если class loader неправильно настроен, одно приложение
может случайно заставить другое использовать wrong версию

Мой чек-лист отладки

# 1. Получить полный stack trace
# (включить детальный лог)

# 2. Посмотреть версии зависимостей
mvn dependency:tree | grep -i <library-name>

# 3. Найти конфликты версий
mvn dependency:tree | sort | uniq -d

# 4. Проверить классе в jar'е
unzip -l ~/.m2/repository/.../library.jar | grep <ClassOrMethod>

# 5. Посмотреть сигнатуру метода
javap -cp <jar> <ClassName>

# 6. Очистить и перебилдить
mvn clean install -U  # -U = force update from repositories

# 7. Проверить что скомпилировалось
mvn clean compile  # Видишь compile-time ошибки?

# 8. Запустить с verbose logging
java -verbose:class MyApp  # Показывает какие классы загружаются

Инструменты которыми я пользуюсь

Maven Helper плагин в IntelliJ

View → Show Maven Helper
↓
Визуально показывает граф зависимостей и конфликты

JAD decompiler

Если нужно посмотреть реальный bytecode:

jad -sjava path/to/ClassA.class

JProfile (профайлер)

Для больших приложений:

jprobes MyApp.jar

Как избежать в будущем

  1. Используй Spring Boot parent для управления версиями
  2. Exclude конфликтующие зависимости:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.6.0.Final</version>
</dependency>
  1. Тесты при запуске — включи простой smoke test:
@SpringBootTest
public class ApplicationStartupTest {
    @Test
    public void contextLoads() {
        // Если запустилось без ошибок — хорошо
    }
}
  1. CI/CD — build в docker'е с чистым environment

Вывод

MissingMethodException не появляется просто так. Систематический approach:

  1. Read full stacktrace
  2. Check dependency tree for conflicts
  3. Verify jar file contains the method
  4. Clean build and retry
  5. Use version management (BOM files)
  6. Add smoke tests

Для 95% случаев это проблема версий и конфликтов in classpath. Остальные 5% — это class loader проблемы в app servers.

Помни: compile-time ошибки легко видны, runtime ошибки нужно систематически отлаживать.

Что будешь делать, если при запуске проекта все появляется MissingMethodException | PrepBro