Java AbstractMethodError explained and demonstrated

  Pi Ke        2016-07-22 22:03:20       12,882        0    

According to Oracle Java API documentation, AbstractMethodError is a kind of runtime error where the application is having some incompatible changes which leads to a missing implementation of an abstract method. Below is the official description.

Thrown when an application tries to call an abstract method. Normally, this error is caught by the compiler; this error can only occur at run time if the definition of some class has incompatibly changed since the currently executing method was last compiled.

Well this can happen in cases where there are inconsistent library upgrade. For example, if a library has its framework and its implementation separated in two jars, ideally these two jars should be upgraded at the same time if there is any code update to the framework. But if somehow the upgrade encounters some problem where the framework is not upgraded but the implementation is getting upgraded. And at the same time if the method signature in an interface has been changed, the AbstractMethodError would occur if the application happens to call this method.

Let's see a demo on how this can happen. Now assume we have an Access library which is to access some strings. We have an interface and an implementation for it. The interface is in a fw package and it will be in a testfw.jar, and the implementation code is in an impl package and it will be in a testimpl.jar.

For the first version of the library, the codes for the interface and the implementation are directly using a String as parameter. 

Access.java

package fw;

public interface Access {
	public void access(String str);
}

AccessImpl.java

package impl;

import fw.Access;

public class AccessImpl implements Access {
	public void access(String str) {
		System.out.println("String " + str + " gets accessed");
	}
}

This is v1 of the library and Access.class is in testfw.jar and AccessImpl.class is in testimpl.jar.

And we now changed our mind and we want to redesign the library and accept an char[] array as the parameter so that more operations can be done on it when accessed. Below is the new version of the library code.

Access.java

package fw;

public interface Access {
	public void access(char[] chars);
}

AccessImpl.java

package impl;

import fw.Access;

public class AccessImpl implements Access {
	public void access(char[] chars) {
		System.out.println("String(chars) " + new String(chars) + " gets accessed");
		// More operation below
	}
}

After rebuilding the jars, a new version of the library is generated. Let's call it v2.

Originally we may have a program which uses the v1 library and has the following code:

import fw.Access;
import impl.AccessImpl;

public class AccessTest {
	public static void main(String[] args) {
		Access access = new AccessImpl();
		access.access("test");
	}
}

When running with the below command, there will be no issues.

java -cp v1\testfw.jar;v1\testimpl.jar;. AccessTest

Now if we run below command, there will be AbstractMethodError error.

java -cp v1\testfw.jar;v2\testimpl.jar;. AccessTest

The v2 of impl doesn't implements the method in v1's interface, but the application code calls the v1's method hence it will give the AbstractMethodError.

The takeaway from this post is that be careful when doing library upgrade, especially when there are coreqs among different jars. 

One final question, what if below command is ran, what will be the result?

java -cp v2\testfw.jar;v1\testimpl.jar;. AccessTest

JAVA  ABSTRACTMETHODERROR 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Why cannot an IT guy find a girlfirend