The follow code compiles but causes a java.lang.VerifyError
. The error occurs even if the run() method is not executed.
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class TestCase {
public static void main(String[] args) {
new TestCase().run();
}
public void run() {
class Inner {
}
Map<String, Inner> map = new HashMap<>();
Function<String, Inner> function = (name) -> {
Inner i = map.get(name);
if (i == null) {
i = new Inner();
map.put(name, i);
}
return i;
};
function.apply("test");
}
}
The Error:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
TestCase.lambda$0(Ljava/util/Map;Ljava/lang/String;)LTestCase$1Inner; @20: invokespecial
Reason:
Type 'java/util/Map' (current frame, stack[2]) is not assignable to 'TestCase'
Current Frame:
bci: @20
flags: { }
locals: { 'java/util/Map', 'java/lang/String', 'TestCase$1Inner' }
stack: { uninitialized 15, uninitialized 15, 'java/util/Map' }
Bytecode:
0000000: 2a2b b900 2d02 00c0 0032 4d2c c700 15bb
0000010: 0032 592a b700 344d 2a2b 2cb9 0037 0300
0000020: 572c b0
Stackmap Table:
append_frame(@33,Object[#50])
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
at java.lang.Class.getMethod0(Class.java:2937)
at java.lang.Class.getMethod(Class.java:1771)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
However, if I move the 'Inner' class to be an inner class of TestCase (instead of declared in a method), the error goes away. Or, if I use an anonymous class to define the Function, the error goes away. It seems to be an issue with a class declared in the method and the use of a lamba.
Is this a JVM bug? Or am I missing something? I am using Oracle's Java 8. The error happens both on the command line and within Eclipse 4.4.
EDIT: I upgraded to the latest JDK: java version "1.8.0_11" Java(TM) SE Runtime Environment (build 1.8.0_11-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)
When compile via javac manually and run it works fine. If I run the class compiled by Eclipse, it doesn't. So now I suspect that the Eclipse compiler has a bug.