我收到这个非常神秘的错误:
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)
但我不可能明白出了什么问题。这似乎表明我正在 TestUtils
类中的 Object
和 CharSequence
上调用连接方法(我认为这不是当我运行 the test that triggers this 时会被感动),但听起来非常接近 another function I wrote这里没有使用它。
发生了一些我无法理解的事情。有人有什么想法吗?
配套 JetBrains 错误:KT-17210
最佳答案
由于我没有字节码可供研究,所以以下所有解释都建立在一个假设之上:Kotlin 的智能转换再次错误。
tl;dr JVM 验证整个类,而不仅仅是使用的比例。
这种情况发生在以下步骤:
- 测试运行。 Junit 找到测试并尝试调用
org.bh.tools.base.math.NumberConversionKtTest::Number_float32Value
反射。这触发了类NumberConversionKtTest
的加载、链接和初始化。 。一切都很好。 - 此方法调用
org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
,它位于尚未加载的类中(请注意前一个类没有的试用Kt
)。 JVM 找到、加载、链接并初始化它。 assertNumbersClose
现在正在执行,即创建一个新帧并将其插入堆栈。执行完部分字节码后,程序流程转到第488行,发现一条方法调用指令,要求JVM执行org.bh.tools.base.strings.TestUtils
类中的一个方法。 。该类尚未加载,因此 JVM 开始加载新类。- JVM 加载该类,并且在verifying期间,它找到了方法
concat
,不是assertNumbersClose
中使用的那个,不好。它停止验证VerifyError
。因为方法differingCharacters
尚未执行,即没有创建新帧并将其插入堆栈,它不在堆栈跟踪上,因此您会看到org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
在顶部。
可能的解决方法
您需要修复 concat
方法的字节码,不知何故。您有以下解决方法。
- 尝试升级 kotlin 编译器。我记得 kotlin 1.1 中修复了一些与 smartcast 相关的问题。
由于此错误是 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) } }
这有时适用于某些人。
如果所有这些都不起作用,请切换到纯 Java 并放置
concat
在另一个类(class)。这解决了大多数(如果不是全部)kotlin 问题。
关于jvm - 非常神秘的运行时错误: Bad type operand on stack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43164689/