非常神秘的运行时错误:堆栈上的错误类型操作数

时间:2017-04-02 04:39:02

标签: 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

但我无法理解出了什么问题。它似乎表明我在ObjectCharSequenceTestUtils内调用连接方法(当我运行时,我认为它不会被触及the test that triggers this),但声音强大接近another function I wrote,这里没有使用过。

有些事情发生了,我无法理解。有没有人有任何想法?

Companion JetBrains错误:KT-17210

2 个答案:

答案 0 :(得分:1)

由于我没有要研究的字节码,所以下面的所有解释都建立在一个假设上:Kotlin再次出现了错误的错误。

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

情况发生在以下步骤中:

  1. 测试跑了。 Junit找到了测试并尝试调用@Override public boolean accept() throws IOException { String sep = ((SeparatorDeliveringTokeniser) input).getSeparator(); // a preceding separator can only be an empty String if we are currently // dealing with the first token and if the sequence starts with a token if (!sep.isEmpty()) { // ... do something with the preceding separator } // then get the token... String token = getTerm(); // ... do something with the token // my filter does no filtering! Every token is accepted...: return true; } @Override public void end() throws IOException { // deals with trailing separator at the end of a sequence of tokens and separators (if there is one, i.e. if it doesn't end with a token) String sep = ((SeparatorDeliveringTokeniser) input).getSeparator(); // NB will be an empty String if there is no trailing separator if (!sep.isEmpty()) { // ... do something with this trailing separator } } 反射。这触发了类org.bh.tools.base.math.NumberConversionKtTest::Number_float32Value的加载,链接和初始化。一切都很好。
  2. 此方法调用NumberConversionKtTest,它位于尚未加载的类中(注意前一个类没有的试验org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose)。 JVM找到,加载,链接和初始化它。
  3. 现在正在执行Kt,即创建一个新帧并将其推入堆栈。在执行一些字节码之后,程序流程移到第488行,并找到一个方法调用指令,该指令要求JVM执行位于类assertNumbersClose中的方法。这个类还没有加载,所以JVM开始加载一个新类。
  4. JVM加载该类,并且在verifying期间,它发现方法org.bh.tools.base.strings.TestUtils,而不是concat中使用的方法,并不好。它会停止使用assertNumbersClose进行验证。因为方法VerifyError尚未执行,即没有创建新框架并将其推入堆栈,所以它不在堆栈跟踪中,因此您在顶部看到differingCharacters
  5. 可行的解决方法

    您需要以某种方式修复org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose方法的字节码。你有以下wrokaround。

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

      concat

      有时适用于某些人。

    3. 如果所有这些都不起作用,请切换到普通Java并将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) } } 放在另一个类中。这解决了大多数(如果不是全部)kotlin问题。

答案 1 :(得分:1)

根据Dmitry PetrovAlexander Chernikov,这是Kotlin 1.1.1中的编译器错误,已在1.1.2版本中修复。