我得到了这个非常神秘的错误:
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)
但我无法理解出了什么问题。它似乎表明我在Object
和CharSequence
类TestUtils
内调用连接方法(当我运行时,我认为它不会被触及the test that triggers this),但声音强大接近another function I wrote,这里没有使用过。
有些事情发生了,我无法理解。有没有人有任何想法?
答案 0 :(得分:1)
由于我没有要研究的字节码,所以下面的所有解释都建立在一个假设上:Kotlin再次出现了错误的错误。
情况发生在以下步骤中:
@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
的加载,链接和初始化。一切都很好。NumberConversionKtTest
,它位于尚未加载的类中(注意前一个类没有的试验org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
)。 JVM找到,加载,链接和初始化它。 Kt
,即创建一个新帧并将其推入堆栈。在执行一些字节码之后,程序流程移到第488行,并找到一个方法调用指令,该指令要求JVM执行位于类assertNumbersClose
中的方法。这个类还没有加载,所以JVM开始加载一个新类。org.bh.tools.base.strings.TestUtils
,而不是concat
中使用的方法,并不好。它会停止使用assertNumbersClose
进行验证。因为方法VerifyError
尚未执行,即没有创建新框架并将其推入堆栈,所以它不在堆栈跟踪中,因此您在顶部看到differingCharacters
。您需要以某种方式修复org.bh.tools.base.math.NumberConversionKtTestKt.assertNumbersClose
方法的字节码。你有以下wrokaround。
由于此错误是kotlin编译器未能为smartcast发出CHECKCAST,您可能会尝试添加手动转换,如下所示:
concat
有时适用于某些人。
如果所有这些都不起作用,请切换到普通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 Petrov和Alexander Chernikov,这是Kotlin 1.1.1中的编译器错误,已在1.1.2版本中修复。