Jvm 非常神秘的运行时错误:堆栈上的操作数类型错误
我发现了一个非常神秘的错误:Jvm 非常神秘的运行时错误:堆栈上的操作数类型错误,jvm,kotlin,Jvm,Kotlin,我发现了一个非常神秘的错误: java.lang.VerifyError:操作数堆栈上的类型错误 例外情况详情: 地点: org/bh/tools/base/strings/TestUtils.concat(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence@28:invokevirtual 原因: 类型“java/lang/Object”(当前帧,堆栈[1])不可分配给“java/lang/String” 当前帧
java.lang.VerifyError:操作数堆栈上的类型错误
例外情况详情:
地点:
org/bh/tools/base/strings/TestUtils.concat(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence@28:invokevirtual
原因:
类型“java/lang/Object”(当前帧,堆栈[1])不可分配给“java/lang/String”
当前帧:
密件抄送:@28
标志:{}
局部变量:{'java/lang/Object','java/lang/CharSequence'}
堆栈:{'java/lang/StringBuilder','java/lang/Object'}
字节码:
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
堆栈映射表:
同一帧(@42)
同一帧(@67)
在org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose(NumberConversionKtTest.kt:488)
位于org.bh.tools.base.math.NumberConversionKtTest.Number\u float32Value(NumberConversionKtTest.kt:47)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中
位于java.lang.reflect.Method.invoke(Method.java:498)
位于org.junit.runners.model.FrameworkMethod$1.runReflectVeCall(FrameworkMethod.java:50)
位于org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
位于org.junit.runners.model.FrameworkMethod.invokeeexplosive(FrameworkMethod.java:47)
位于org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
位于org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
位于org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:363)
位于org.junit.runners.Suite.runChild(Suite.java:128)
位于org.junit.runners.Suite.runChild(Suite.java:27)
位于org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
位于org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
位于org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
访问org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
位于org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
位于org.junit.runners.ParentRunner.run(ParentRunner.java:363)
位于org.junit.runner.JUnitCore.run(JUnitCore.java:137)
位于com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
位于com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:58)
位于com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
位于com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
在这一行:
我认为它涉及到这个功能:
但我不可能理解出了什么问题。这似乎表明我在调用TestUtils
类中的对象
和CharSequence
上的串联方法(我认为在运行时不会触及该方法),但听起来非常接近此处未使用的方法
发生了一些我无法理解的事情。有人有什么想法吗?
伴随JetBrains的bug:因为我没有字节码要研究,下面所有的解释都建立在一个假设上:Kotlin再次犯了智能铸造错误 tl;dr JVM验证整个类,而不仅仅是使用的比例。 这种情况发生在以下步骤中:
org.bh.tools.base.math.NumberConversionKtTest::Number\u float32Value
反射。这触发了类NumberConversionKtTest
的加载、链接和初始化。一切都很好org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
,它位于尚未加载的类中(请注意前一个类没有的试用Kt
)。JVM找到、加载、链接并初始化了它李>
assertNumbersClose
现在正在执行,即创建一个新帧并将其推入堆栈。在执行一些字节码之后,程序流移动到第488行,并找到一条方法调用指令,该指令要求JVM执行类org.bh.tools.base.strings.TestUtils中的方法。这个类还没有加载,所以JVM开始加载一个新类
concat
,而不是assertNumbersClose
中使用的方法不好。它会停止验证,并出现验证错误
。由于方法differingCharacters
尚未执行,即未创建新框架并将其推入堆栈,因此它不在堆栈跟踪上,因此您可以看到顶部的org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
可能的解决办法 您需要以某种方式修复
concat
方法的字节码。你有下面这些问题
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)
}
}