This program compiles without error. It fails with an IllegalAccessError at runtime because A2#test does an invokevirtual A2#getI; since A2 doesn't declare getI, A1#getI method is resolved and is inaccessible from A2. It may appear that A2#test should do an invokeinterface I1#getI but the JLS doesn't want this to happen (for good reason - A2 logically has a member getI).
class A1 {
private int getI() {
return 1;
}
}
interface I1 {
int getI();
}
abstract class A2 extends A1 implements I1 {
public void test() {
System.out.println(getI());
}
}
class A3 extends A2 {
public int getI() {
return 2;
}
}