exception原因java.lang.VerifyError:操作数堆栈上的错误类型

下面简单的java代码在操作数堆栈exception发送java.lang.VerifyError:Bad类型

public class TestJavaCodes { int parentData = 0; public void init() { A ob = new B(); } public static void main(String[] args) { TestJavaCodes testJavaCodes = new TestJavaCodes(); testJavaCodes.init(); } public static class A { public A(MyLambdaFunc lambdaFunc) { } } public class B extends A { public B() { super((data1, type) -> { parentData = 1; }); } } @FunctionalInterface public static interface MyLambdaFunc { public void onData(String data, int type); } } 

如果我删除代码

 parentData = 1 

B的构造函数来看,exception不会出现。

任何人都可以说出原因吗?

出现问题是因为你的lambda表达式不引用thisthis成员,而是引用this外部成员。 你有没有写过B级的

 public class B extends A { int innerData; public B() { super((data1, type) -> innerData = 1); } } 

编译器毫无疑问地拒绝了它,因为访问innerData意味着访问this

关于外部实例的观点是,它是一个常量,当内部实例尚未完全构造时,它甚至可用。 因此接受代码是正确的,但不幸的是编译器生成的代码试图通过内部类实例的隐式字段访问外部实例,因此lambda表达式需要内部类的实例并尝试使用未完全构造的内部类实例产生错误。

可以很容易地certificate代码可以正确编译:

 public class B extends A { public B() { this(TestJavaCodes.this); } private B(TestJavaCodes outer) { super((data1, type) -> outer.parentData = 1); } } 

通过这个小的更改,lambda表达式引用外部实例而不访问内部实例,并且不会出现错误。

似乎这些代码根本不应该编译。 我最小化了你的代码:

 public class CompilerBug { int var = 0; public static void main(String[] args) { new CompilerBug().new Inner(); } public class Inner { public Inner(Runnable r) {} public Inner() { this(() -> { var = 1; }); } } } 

它是由javac 1.8.0.25,1.8.0.40和1.9b57编译而没有问题的。 每个编译版本在启动时都会产生相同的输出:

 Exception in thread "main" java.lang.VerifyError: Bad type on operand stack Exception Details: Location: CompilerBug$Inner.(LCompilerBug;)V @3: invokedynamic Reason: Type uninitializedThis (current frame, stack[2]) is not assignable to 'CompilerBug$Inner' Current Frame: bci: @3 flags: { flagThisUninit } locals: { uninitializedThis, 'CompilerBug' } stack: { uninitializedThis, 'CompilerBug', uninitializedThis } Bytecode: 0000000: 2a2b 2aba 0003 0000 b700 04b1 at CompilerBug.main(CompilerBug.java:5) 

此代码不是由ECJ编译器编译的。 它报告编译错误:

 ---------- 1. ERROR in C:\projects\Test\src\CompilerBug.java (at line 12) this(() -> { ^^^^^ Cannot refer to 'this' nor 'super' while explicitly invoking a constructor ---------- 1 problem (1 error) 

所以它看起来像是javac编译器中的一个错误:它应该返回一个编译错误(如ECJ)。

我没有在OpenJDK bug跟踪器中找到类似的bug,因此通过webform提交了一个新的bug报告。 如果Java人员正在阅读此内容,则分配的内部审阅ID为JI-9021379。

更新:接受错误报告( JDK-8129740 )