Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.VerifyError with inner class & lambda

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.

like image 638
dontocsata Avatar asked Nov 10 '22 03:11

dontocsata


1 Answers

verify error is thrown when your compiler generates a code that is not verifiable by verifier. when the "verifier" detects that a class file, though well formed, contains some sort of internal inconsistency or security problem. So it is clearly an issue with your eclipse compiler as you have suggested. it is unable to properly compile these constructs.

like image 177
faisalbhagat Avatar answered Nov 14 '22 22:11

faisalbhagat