JDK-8038776 : VerifyError when running successfully compiled java class
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2014-03-30
  • Updated: 2015-01-21
  • Resolved: 2014-06-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u40Fixed 9 b22Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

FULL OS VERSION :
Linux d 3.11.0-19-generic #33-Ubuntu SMP Tue Mar 11 18:48:34 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
Compiling the attached code does not produce an error. However, execution fails with a VerifyError.


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 attached class.
- Run "java Test".

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:

The second call in the runTest() method should execute without any problems and behave the same way as the first.

Actual:

The second call compiles fine but corrupts the class file so it can not be executed.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    Test.lambda$runTest$2(LTest$Worker;)V @2: invokedynamic
  Reason:
    Type 'Test$Worker' (current frame, stack[1]) is not assignable to 'Test'
  Current Frame:
    bci: @2
    flags: { }
    locals: { 'Test$Worker' }
    stack: { 'Test$Worker', 'Test$Worker' }
  Bytecode:
    0000000: 2a2a ba00 0b00 00b6 000c b1            

	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)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.function.Function;

/**
 * @author Yawkat
 */
public class Test {
    public static void main(String[] args) { new Test().runTest(); }

    private void runTest() {
        Worker worker = new Worker();
        run(() -> worker.print(field -> new SomeClass(field)));
        run(() -> worker.print(SomeClass::new));
    }

    private void run(Runnable runnable) {
        runnable.run();
    }

    private class SomeClass {
        final Object field;

        SomeClass(Object field) {
            this.field = field;
        }
    }

    private static class Worker {
        void print(Function<Object, Object> i) {
            System.out.println(i.apply(null));
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Replacing "SomeClass::new" with "field -> new SomeClass(field)" resolves the issue.


Comments
ManualVerify: Bug verified manually in promoted results for build JDK9-b22
10-07-2014

Test(s) was added with this push --- URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/2b6b96ed3878 User: rfield Date: 2014-06-25 18:22:47 +0000
27-06-2014

If this is a P4 - it does not need release team approval. I've removed the defer-request label.
18-06-2014

8u20-defer-request: 8037404, 8038776, 8044737, and 8044748 form a cluster of issues related to inadequate handling of constructor references to nested classes in method references. They cause crashes of the compiler and/or the running user code, and thus are high impact. They have been reported in at least five cases in fully supported code and thus this is medium likelihood. The workaround is to manually convert them to lambdas which is a low hurdle workaround. Thus ILM of HML. The fix requires rearchitecting of how method references are handled, with hundreds of lines of code change, and thus is inappropriate for an update release. The fix is under review for push to JDK9.
16-06-2014

Also the SomeClass must be an inner class. Thus, the class need not be generic, there need not be an explicit constructor argument, and the method calls don't matter. But there must be a constructor method reference to an inner class of this class within a lambda.
29-05-2014

Reproducible with the following simplified test case: /** * Derived from code by: * @author Yawkat */ public class Test { public static void main(String[] args) { new Test().runTest(); } private void runTest() { Runnable r = (() -> { Sup w = SomeClass::new; } ); } private class SomeClass { SomeClass() { } } } interface Sup { Object get(); } With the following slightly different error: rror: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.VerifyError: Bad local variable type Exception Details: Location: Test.lambda$runTest$0()V @0: aload_0 Reason: Type top (current frame, locals[0]) is not assignable to reference type Current Frame: bci: @0 flags: { } locals: { } stack: { } Bytecode: 0000000: 2aba 0006 0000 4bb1 at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2687) at java.lang.Class.getMethod0(Class.java:2933) at java.lang.Class.getMethod(Class.java:1770) at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:568) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:535)
29-05-2014

Reproducible in jdk9-development. The lambda in the lambda does not cause the problem, only the method reference in the lambda. The lambda in the lambda can be removed from the test case: run(() -> worker.print(field -> new SomeClass(field)));
29-05-2014

This bug arose from a StackOverflow question: http://stackoverflow.com/questions/22738962/using-java-8-someclassnew-for-inner-classes
30-03-2014