Java - AbstractMethodError 원인 및 해결

AbstractMethodError는 구현되지 않은 abstract 메소드를 호출할 때 발생합니다. Java 코드를 컴파일할 때, abstract 메소드를 구현하지 않으면 컴파일 에러가 발생하지 않기 때문에 이런 문제가 발생하지 않습니다. 그럼 어떤 상황에서 이런 에러가 발생할까요?

java.lang.AbstractMethodError
    at javax.persistence.Persistence$PersistenceUtilImpl.isLoaded(Unknown Source)
    at org.hibernate.validator.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:61)

1. 문제가 발생하는 케이스?

문제는 Java 프로그램에서 JAR 형식으로 외부 라이브러리를 사용할 때 문제가 발생할 수 있습니다. 예를 들어, v1 라이브러리를 사용하다가 v2로 변경하였는데 interface에서 새로운 abstract method를 추가했을 때 입니다. 내 프로그램은 신규 v2 라이브러리를 사용하기 때문에 문제가 발생하지 않습니다. 하지만 내가 사용하는 외부 JAR가 v1 라이브러리를 사용하여 컴파일되었다면 문제가 발생할 수 있습니다. 이 JAR에서 생성된 객체가 내가 구현한 객체로 전달될 수 있고, 당연히 v2에서 제공하는 신규 메소드를 사용할 수 있다고 생각하여 신규 메소드를 호출할 수 있습니다. 사실 이 객체는 v1에서 만들어졌고, 객체가 생성되는데 사용된 클래스에는 신규 메소드가 추가되지 않은 클래스입니다. 이럴 때 AbstractMethodError가 발생할 수 있습니다.

2. Example

위에서 설명한 것을 예제로 다시 설명해보면...

아래와 같은 List를 제공하는 PlainList_v1 라이브러리를 사용하고 있습니다.

public interface List {
  void add(int n);
  void remove(int n);
}

이것은 매우 기본적인 라이브러리라서, 내 프로그램에서도 사용하고, 내가 사용하는 다른 외부 라이브러리 JAR에서도 사용되고 있습니다.

ArrayList도 PlainList_v1 라이브러리에서 제공하고 있고, 이런식으로 객체를 만들어 사용하고 있었습니다.

List list = new ArrayList();
list.add(10);
list.remove(10);

어느날 PlainList_v2에서 get() 메소드가 추가되었습니다. 내 프로그램에서 이 기능이 필요하여 v2로 의존성을 업그레이드하였습니다.

public interface List {
  void add(int n);
  void remove(int n);
  int get(int index);
}

내 프로그램에서는 모두 v2를 사용하기 때문에 문제가 없습니다. 하지만 PlainList_v1를 사용하는 다른 외부 JAR의 버전은 실수로 변경하지 못하였습니다.

프로그램을 실행해보니, 아래와 같이 외부 JAR의 메소드를 실행하여 ArrayList 객체를 전달받을 때가 있었고, 내 프로그램에서 만든 ArrayList 객체처럼 get()을 호출하였습니다. 이 때 AbstractMethodError가 발생하였습니다.

List list = getArrayListFromOtherJar();

list.add(10);
list.get(0);

위의 코드에서 getArrayListFromOtherJar()는 PlainList_v1에서 생성된 객체입니다. 이 객체를 생성하는데 사용한 클래스에는 get() 메소드가 정의되지 않았을 때 입니다. 이 때 get()을 호출하면 이 객체에 abstract 메소드가 정의되어있지 않다는 의미의 AbstractMethodError 에러가 발생할 수 있습니다.

이 에러는 프로그램을 테스트할 때는 문제가 발생하지 않다가, 특정 조건에 외부 라이브러리로부터 객체를 받아서 처리할 때 문제가 발생할 수 있습니다. 운이 없다면 배포가 된 후에 코너 케이스에서 문제가 발생할 수도 있습니다.

3. 해결 방법

만약 문제가 발생했다면, 내가 사용하는 외부 JAR에서 서로 동일한 라이브러리를 사용하는지 확인하고 의존성 문제는 없는지 확인해야 합니다.

References

Loading script...

Related Posts

codechachaCopyright ©2019 codechacha