简体   繁体   English

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

[英]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.

相关问题 java.lang.VerifyError:操作数堆栈上的类型错误 - java.lang.VerifyError: Bad type on operand stack JVM错误? java.lang.VerifyError:操作数堆栈上的错误类型 - JVM bug? java.lang.VerifyError: Bad type on operand stack 线程“主”java.lang.VerifyError 中的异常:操作数堆栈上的错误类型 Java 8 121 但不在 ZD52387880E1EA22817A72D3759213891 上 - Exception in thread “main” java.lang.VerifyError: Bad type on operand stack Java 8 121 but not on Java 11 异常java.lang.VerifyError:Heron中发生了操作数堆栈上的错误类型 - The exception java.lang.VerifyError: Bad type on operand stack happend in Heron 线程“ main”中的异常java.lang.VerifyError:操作数堆栈上的类型错误 - Exception in thread “main” java.lang.VerifyError: Bad type on operand stack java.lang.VerifyError:方法com.sun.net.httpserver.spi.HttpServerProvider中的操作数堆栈上的类型错误 - java.lang.VerifyError: Bad type on operand stack in method com.sun.net.httpserver.spi.HttpServerProvider BiPredicate lambda 导致 java.lang.VerifyError: 操作数堆栈上的类型错误,我该如何解决? - BiPredicate lambda is causing a java.lang.VerifyError: Bad type on operand stack, how do I fix this? java.lang.VerifyError:尝试运行JDK提供的HttpServer时操作数堆栈上的错误类型 - java.lang.VerifyError: Bad type on operand stack when trying to run HttpServer provided by JDK taskdef java.lang.VerifyError:当TEAM CITY执行构建时,操作数堆栈上的类型错误 - taskdef java.lang.VerifyError: Bad type on operand stack when TEAM CITY executes build Parse + Robolectric导致java.lang.VerifyError:操作数堆栈上的错误类型 - Parse + Robolectric causing java.lang.VerifyError: Bad type on operand stack
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM