FULL PRODUCT VERSION :
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
FULL OS VERSION :
Mac OS X 10.9.5
Windows 7
A DESCRIPTION OF THE PROBLEM :
A lambda nested in an anonymous class cannot call a protected method inherited by the class surrounding the anonymous class.
The compiler accepts this code but running it produces a java.lang.IllegalAccessError.
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Yes
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the test classes and run class bbb.Test
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:
The method aaa.AbstractClass#myDo() is called and prints "It works" to System.out
Actual:
A BootstrapMethodError is thrown caused by an IllegalAccessError
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.BootstrapMethodError: java.lang.IllegalAccessError: tried to access method aaa.AbstractClass.myDo()V from class bbb.Test$1
at bbb.Test$1.call(Test.java:22)
at bbb.Test.doTest(Test.java:26)
at bbb.Test.main(Test.java:31)
Caused by: java.lang.IllegalAccessError: tried to access method aaa.AbstractClass.myDo()V from class bbb.Test$1
at java.lang.invoke.MethodHandleNatives.resolve(Native Method)
at java.lang.invoke.MemberName$Factory.resolve(MemberName.java:962)
at java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:987)
at java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:1390)
at java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:1746)
at java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:477)
... 3 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package aaa;
/**
* <hr>
* <p>User: mathias</p>
* <p>Date: 22.09.15</p>
* <p>Time: 15:37</p>
*/
public abstract class AbstractClass {
protected final void myDo() {
System.err.println("It works!");
}
}
----------------------------------------------------
package bbb;
import aaa.AbstractClass;
import java.util.concurrent.Callable;
/**
* <hr>
* <p>User: mathias</p>
* <p>Date: 22.09.15</p>
* <p>Time: 15:39</p>
*/
public final class Test extends AbstractClass {
public Test() {
}
public void doTest() throws Exception {
new Callable<Void>() {
@Override
public Void call() throws Exception {
final Runnable r = Test.this::myDo;
r.run();
return null;
}
}.call();
}
public static void main(String[] args) throws Exception {
final Test test = new Test();
test.doTest();
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
1. Replace the anonymous class with a lambda expression
2. Replace the lamba expression with an anonymous class
BUT: Both workarounds do not address the initial problem, that the unmodified code is accepted by the compiler but rejected at runtime!