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-queue 와 baeldung-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.0 과 baeldung-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. 실제 사례
간단한 BaeldungQueue 및 GoodQueue 시나리오를 통해 애플리케이션이 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 에 직면했을 때 이 오류를 잘 이해하면 문제를 빠르게 해결할 수 있습니다.