Java Method Overriding Is FUBAR Part 9 of ∞

Java 8 introduces default methods. In the current HotSpot implementation this makes adding a private method to a non-final class a binary breaking change (contrary to what the JLS says about this).

Here's an example. Suppose you have two separate code bases Lib and App, shipped by different parties. App depends on Lib.

Lib defines a class B:

public class B {

}

App defines an interface I and a class D:

public interface I {

default void m() {

System.out.println("I.m");

}

}

public class D extends B implements I {

public static void main(String[] args) {

D d = new D();

d.m();

}

}

All is well in the world. Now Lib ships a new version that includes a new version of class B:

public class B {

private void m() { }

}

Now when you run D the output is:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method B.m()V from class D

at D.main(D.java:4)

You could argue that this is "just" an implementation bug, but I posted it as part of this series because it is symptomatic of the mess that is Java's method dispatch story.