异常 java.lang.VerifyError 的原因:操作数堆栈上的类型错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30365106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reason for the exception java.lang.VerifyError: Bad type on operand stack
提问by dGayand
The below simple java code sends the java.lang.VerifyError: Bad type on operand stackexception
下面的简单java代码发送 java.lang.VerifyError:操作数堆栈异常类型错误
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.
fromB
的构造函数,不会出现异常。
Can any one tell the reason for this?
任何人都可以说出这是什么原因吗?
采纳答案by Holger
The problem arises because your lambda expression does not reference this
or a member of this
but a member of the outerthis
. Had you written class B
like
出现问题是因为您的 lambda 表达式没有引用this
或成员,this
而是外部this
. 假如你写的类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 canbe 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 表达式就引用了外部实例,而无需访问内部实例,也不会出现错误。
回答by Tagir Valeev
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. Every compiled version produces the same output when launching:
它由 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.<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. It reports a compilation error:
此代码不是由 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)
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. If Java folks are reading this, the internal review ID assigned is JI-9021379.
我在 OpenJDK bug tracker 中没有发现类似的 bug,所以通过 webform 提交了一个新的 bug 报告。如果 Java 人员正在阅读本文,则分配的内部 ID 为 JI-9021379。
Update:The bug report is accepted (JDK-8129740)
更新:错误报告被接受(JDK-8129740)