jvm - 非常神秘的运行时错误: Bad type operand on stack

标签 jvm kotlin

我收到这个非常神秘的错误:

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/bh/tools/base/strings/TestUtils.concat(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence; @28: invokevirtual
  Reason:
    Type 'java/lang/Object' (current frame, stack[1]) is not assignable to 'java/lang/String'
  Current Frame:
    bci: @28
    flags: { }
    locals: { 'java/lang/Object', 'java/lang/CharSequence' }
    stack: { 'java/lang/StringBuilder', 'java/lang/Object' }
  Bytecode:
    0x0000000: 2a12 59b8 0012 2b12 43b8 0012 2ac1 005b
    0x0000010: 9900 1a2a bb00 1659 b700 1a5f b600 512b
    0x0000020: b600 5eb6 0052 c000 23b0 2ac1 0016 9900
    0x0000030: 152a c000 162b b600 5e59 1260 b800 63c0
    0x0000040: 0023 b0bb 0016 59b7 001a 2ab6 0047 2bb6
    0x0000050: 005e 5912 65b8 0063 c000 23b0          
  Stackmap Table:
    same_frame(@42)
    same_frame(@67)


    at org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose(NumberConversionKtTest.kt:488)
    at org.bh.tools.base.math.NumberConversionKtTest.Number_float32Value(NumberConversionKtTest.kt:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:58)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

在这一行: https://github.com/BlueHuskyStudios/Blue-Base/blob/ea415b702b87b7a33d90bc13221f44205c38e9f1/JVM/test/org/bh/tools/base/math/NumberConversionKtTest.kt#L488

我认为涉及到这个功能: https://github.com/BlueHuskyStudios/Blue-Base/blob/ea415b702b87b7a33d90bc13221f44205c38e9f1/JVM/src/org/bh/tools/base/strings/String%20Utils.kt#L121-L154

但我不可能明白出了什么问题。这似乎表明我正在 TestUtils 类中的 ObjectCharSequence 上调用连接方法(我认为这不是当我运行 the test that triggers this 时会被感动),但听起来非常接近 another function I wrote这里没有使用它。

发生了一些我无法理解的事情。有人有什么想法吗?


配套 JetBrains 错误:KT-17210

最佳答案

由于我没有字节码可供研究,所以以下所有解释都建立在一个假设之上:Kotlin 的智能转换再次错误。

tl;dr JVM 验证整个类,而不仅仅是使用的比例。

这种情况发生在以下步骤:

  1. 测试运行。 Junit 找到测试并尝试调用 org.bh.tools.base.math.NumberConversionKtTest::Number_float32Value反射。这触发了类NumberConversionKtTest的加载、链接和初始化。 。一切都很好。
  2. 此方法调用 org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose ,它位于尚未加载的类中(请注意前一个类没有的试用Kt)。 JVM 找到、加载、链接并初始化它。
  3. assertNumbersClose现在正在执行,即创建一个新帧并将其插入堆栈。执行完部分字节码后,程序流程转到第488行,发现一条方法调用指令,要求JVM执行org.bh.tools.base.strings.TestUtils类中的一个方法。 。该类尚未加载,因此 JVM 开始加载新类。
  4. JVM 加载该类,并且在verifying期间,它找到了方法concat ,不是 assertNumbersClose 中使用的那个,不好。它停止验证 VerifyError 。因为方法differingCharacters尚未执行,即没有创建新帧并将其插入堆栈,它不在堆栈跟踪上,因此您会看到 org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose在顶部。

可能的解决方法

您需要修复 concat方法的字节码,不知何故。您有以下解决方法。

  1. 尝试升级 kotlin 编译器。我记得 kotlin 1.1 中修复了一些与 smartcast 相关的问题。
  2. 由于此错误是 kotlin 编译器未能为智能转换发出 CHECKCAST,因此您可以尝试添加手动转换,如下所示:

    fun concat(lhs: Any, rhs: CharSequence): CharSequence {
        if (lhs is String) {
            val s: String = lhs as String
            return s.plus(rhs)
        } else if (lhs is StringBuilder) {
            val sb: StringBuilder= lhs as StringBuilder
            return sb.append(rhs)
        } else {
            return StringBuilder().append(lhs).append(rhs)
        }
    }
    

    有时适用于某些人。

  3. 如果所有这些都不起作用,请切换到纯 Java 并放置 concat在另一个类(class)。这解决了大多数(如果不是全部)kotlin 问题。

关于jvm - 非常神秘的运行时错误: Bad type operand on stack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43164689/

相关文章:

java - JVM 如何终止守护线程?或如何编写优雅终止的守护线程

security - 覆盖应用程序的 US_export_policy 和 local_policy jar

java - 为什么 Grails 在 Mac OS x 7 上使用旧的 JVM 编译器?

java - 使用位图工厂在可运行程序中以每秒 30 个图像的速度显示 150 个图像,但它很滞后

java - 为什么 JVM 需要这么长时间来 GC 我无法访问的对象?

android - Robolectric 测试在没有消息的情况下抛出 IllegalArgumentException

android - 如何异步调用rest api并等待所有调用在rx-android中完成

Android MVVM - 数据更改时更新 ViewModel

android - 如何获取当前在 imageview (Kotlin) 中的图像名称?

java - 在现有的Java多项目Gradle构建中添加对Kotlin源的支持