[英]Reason for the exception java.lang.VerifyError: Bad type on operand stack
The below simple java code sends the java.lang.VerifyError: Bad type on operand stack exception 下面简单的java代码在操作数堆栈异常上发送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);
}
}
If I remove the code 如果我删除代码
parentData = 1
from B
's constructor, the exception won't come. 从B
的构造函数来看,异常不会出现。
Can any one tell the reason for this? 任何人都可以说出原因吗?
Seems that such code should not compile at all. 似乎这些代码根本不应该编译。 I minimized your code: 我最小化了你的代码:
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;
});
}
}
}
It's compiled without problems by javac 1.8.0.25, 1.8.0.40 and 1.9b57. 它是由javac 1.8.0.25,1.8.0.40和1.9b57编译而没有问题的。 Every compiled version produces the same output when launching: 每个编译版本在启动时都会产生相同的输出:
Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
CompilerBug$Inner.<init>(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)
This code is not compiled by ECJ compiler. 此代码不是由ECJ编译器编译的。 It reports a compilation error: 它报告编译错误:
----------
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)
So it looks like a bug in javac compiler: it should return a compilation error instead (like ECJ). 所以它看起来像是javac编译器中的一个错误:它应该返回一个编译错误(如ECJ)。
I did not find similar bug in OpenJDK bug tracker, so submitted a new bug report via webform. 我没有在OpenJDK bug跟踪器中找到类似的bug,因此通过webform提交了一个新的bug报告。 If Java folks are reading this, the internal review ID assigned is JI-9021379. 如果Java人员正在阅读此内容,则分配的内部审阅ID为JI-9021379。
Update: The bug report is accepted ( JDK-8129740 ) 更新:接受错误报告( JDK-8129740 )
The problem arises because your lambda expression does not reference this
or a member of this
but a member of the outer this
. 这个问题的产生是因为您的lambda表达式不引用this
或成员this
,但外部的成员this
。 Had you written class B
like 你写过B
级的吗?
public class B extends A {
int innerData;
public B() {
super((data1, type) -> innerData = 1);
}
}
the compiler rejected it without any doubts as accessing innerData
implies accessing this
. 编译器毫无疑问地拒绝了它,因为访问innerData
意味着访问this
。
The point about the outer instance is that it is a constant which is even available when the inner instance has not been fully constructed yet. 关于外部实例的观点是它是一个常量,当内部实例尚未完全构造时它甚至可用。 So it's correct to accept the code but unfortunately the compiler generates code which attempts to access the outer instance via an implicit field of the inner class instance, thus the lambda expression requires an instance of the inner class and attempting to use the not fully constructed inner class instance produces the error. 因此接受代码是正确的,但不幸的是编译器生成的代码试图通过内部类实例的隐式字段访问外部实例,因此lambda表达式需要内部类的实例并尝试使用未完全构造的内部类实例产生错误。
It can be easily demonstrated that the code can be compiled correctly: 可以很容易地证明代码可以正确编译:
public class B extends A {
public B() {
this(TestJavaCodes.this);
}
private B(TestJavaCodes outer) {
super((data1, type) -> outer.parentData = 1);
}
}
with that small change, the lambda expression refers to the outer instance without accessing the inner instance and no error arises. 通过这个小的更改,lambda表达式引用外部实例而不访问内部实例,并且不会出现错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.