1. 개요

때때로 우리는  애플리케이션에서 런타임에 AbstractMethodError만날 수 있습니다 . 이 오류를 잘 모르는 경우 문제의 원인을 파악하는 데 시간이 걸릴 수 있습니다.

이 예제에서는 AbstractMethodError 를 자세히 살펴볼 것 입니다. AbstractMethodError무엇 이며 언제 발생할 수 있는지 이해할 것입니다.

2. AbstractMethodError 소개

AbstractMethodError 는 응용 프로그램이 구현되지 않은 추상 메서드를 호출하려고 할 때 발생합니다. 

구현되지 않은 추상 메서드가 있으면 컴파일러가 먼저 불만을 표시합니다. 따라서 응용 프로그램이 전혀 빌드되지 않습니다.

런타임에 이 오류가 발생하는 방법을 물어볼 수 있습니다.

먼저 AbstractMethodError 가 Java 예외 계층 구조에 맞는 위치를 살펴보겠습니다 .

java.lang.Object
|_java.lang.Throwable
  |_java.lang.Error
    |_java.lang.LinkageError
      |_java.lang.IncompatibleClassChangeError
        |_java.lang.AbstractMethodError

위의 계층 구조에서 볼 수 있듯이 이 오류는 IncompatibleClassChangeError 의 하위 클래스입니다 . 상위 클래스의 이름에서 알 수 있듯이 AbstractMethodError 는 일반적으로 컴파일된 클래스 또는 JAR 파일 간에 비호환성이 존재할 때 발생합니다.

다음으로 이 오류가 어떻게 발생할 수 있는지 알아보겠습니다.

3. 이 오류가 발생하는 방법

애플리케이션을 빌드할 때 일반적으로 작업을 더 쉽게 하기 위해 일부 라이브러리를 가져옵니다.

우리 애플리케이션에 baeldung-queue  라이브러리 가 포함되어 있다고 가정해 보겠습니다 . baeldung - 큐  라이브러리는 하나의 인터페이스를 포함하는 높은 레벨의 사양 라이브러리이다 :

public interface BaeldungQueue {
    void enqueue(Object o);
    Object dequeue();
}

또한 BaeldungQueue 인터페이스 를 사용하기 위해 BaeldungQueue 구현 라이브러리인 good-queue 를 가져옵니다 . 좋은 큐  라이브러리는 하나 개의 클래스가 :

public class GoodQueue implements BaeldungQueue {
    @Override
    public void enqueue(Object o) {
       //implementation 
    }

    @Override
    public Object dequeue() {
        //implementation 
    }
}

이제 good-queuebaeldung-queue  가 모두 클래스 경로에 있으면 애플리케이션에서 BaeldungQueue 인스턴스를 생성할 수 있습니다 .

public class Application {
    BaeldungQueue queue = new GoodQueue();

    public void someMethod(Object element) {
        queue.enqueue(element);
        // ...
        queue.dequeue();
        // ...
    }
}

여태까지는 그런대로 잘됐다.

언젠가 우리는 baeldung-queue가 버전 2.0을 출시 했고 새로운 방법으로 제공된다는 것을 배웠습니다 .

public interface BaeldungQueue {
    void enqueue(Object o);
    Object dequeue();

    int size();
}

우리는 애플리케이션에서 새로운 size() 메소드 를 사용하려고 합니다. 따라서 baeldung-queue 라이브러리를 1.0 에서 2.0으로 업그레이드합니다 . 그러나 BaeldungQueue 인터페이스 변경 사항 을 구현 하는 새 버전의 good-queue 라이브러리가 있는지 확인하는 것을 잊었습니다 .

따라서  classpath에 good-queue 1.0baeldung-queue 2.0 이 있습니다.

또한 애플리케이션에서 새로운 방법을 사용하기 시작합니다.

public class Application {
    BaeldungQueue queue = new GoodQueue();

    public void someMethod(Object element) {
        // ...
        int size = queue.size(); //<-- AbstractMethodError will be thrown
        // ...
    }
}

우리의 코드는 문제 없이 컴파일될 것입니다.

그러나 런타임에 queue.size() 라인  이 실행되면 AbstractMethodError 가 발생합니다. Good-queue 1.0 라이브러리는 BaeldungQueue 인터페이스 에서 size() 메소드를 구현하지 않기 때문 입니다.

4. 실제 사례

간단한 BaeldungQueueGoodQueue 시나리오를 통해 애플리케이션이 AbstractMethodError를 발생시킬 수 있다는 아이디어를 얻을 수 있습니다

이 섹션에서는 AbstractMethodError 의 실제 예를 볼 것 입니다.

java.sql.Connection 은 JDBC API에서 중요한 인터페이스입니다. 버전 1.7 이후 getSchema() 와 같은몇 가지 새로운 메소드가 Connection 인터페이스에 추가되었습니다 .

H2 데이터베이스는 꽤 빠른 오픈 소스 SQL 데이터베이스입니다. 버전 1.4.192 부터 java.sql.Connection.getSchema() 메소드 지원이 추가되었습니다 . 그러나 이전 버전에서 H2 데이터베이스는 아직 이 방법을 구현하지 않았습니다.

다음으로, 이전 H2 데이터베이스 버전 1.4.191 의 Java 8 애플리케이션에서 java.sql.Connection.getSchema() 메소드를 호출합니다 . 어떤 일이 일어날지 봅시다.

Connection.getSchema() 메서드를 호출하면 AbstractMethodError 가 발생 하는지 확인하기 위해 단위 테스트 클래스를 만들어 보겠습니다 .

class AbstractMethodErrorUnitTest {
    private static final String url = "jdbc:h2:mem:A-DATABASE;INIT=CREATE SCHEMA IF NOT EXISTS myschema";
    private static final String username = "sa";

    @Test
    void givenOldH2Database_whenCallgetSchemaMethod_thenThrowAbstractMethodError() throws SQLException {
        Connection conn = DriverManager.getConnection(url, username, "");
        assertNotNull(conn);
        Assertions.assertThrows(AbstractMethodError.class, () -> conn.getSchema());
    }
}

우리가 테스트를 실행하면 호출 것을 확인, 통과 할 것이다 getSchema ()가 발생 하지 않고 AbstractMethodError를 .

5. 결론

때때로 우리는 런타임에 AbstractMethodError볼 수 있습니다 . 이 글에서는 예시를 통해 에러가 발생하는 경우를 살펴보았습니다.

애플리케이션의 한 라이브러리를 업그레이드할 때 항상 다른 의존성이 라이브러리를 사용하고 있는지 확인하고 관련 의존성을 업데이트하는 것을 고려하는 것이 좋습니다.

반면에 AbstractMethodError직면했을 때 이 오류를 잘 이해하면 문제를 빠르게 해결할 수 있습니다.

항상 그렇듯이 기사의 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .

Junit footer banner