Open
Description
Reproduction steps
Java: Oracle HotSpot 17.0.6+9-LTS-190, OpenJDK Temurin-17.0.8+7.
Scala versions: 2.13.10, 2.13.14.
I faced the behaviour using spray json ("io.spray" %% "spray-json" % "1.3.6"), and I couldn't minimise the snippet to clean scala, but the hint to the nature of the bug is the two workarounds at the bottom of this report.
import spray.json.DefaultJsonProtocol._
import spray.json._
object BadScalac {
def main(args: Array[String]): Unit = {
val msg = (
try Map("block" -> "try").toJson
catch { case _: Throwable => Map("block" -> "catch").toJson }
).prettyPrint + "\n"
println(msg)
}
}
Problem
It gets compiled successfully, but when I run I get
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 152
Exception Details:
Location:
BadScalac$.main([Ljava/lang/String;)V @149: goto
Reason:
Current frame's stack size doesn't match stackmap.
Current Frame:
bci: @149
flags: { }
locals: { 'BadScalac$', '[Ljava/lang/String;' }
stack: { 'spray/json/JsValue' }
Stackmap Frame:
bci: @152
flags: { }
locals: { 'BadScalac$', '[Ljava/lang/String;' }
stack: { 'java/lang/Object', 'spray/json/JsValue' }
Bytecode:
0000000: bb00 1f59 1220 b700 23b2 0028 b200 2db6
0000010: 0031 b200 3604 bd00 3859 03b2 003b b200
0000020: 2d12 3db6 0041 1243 b600 4753 c000 49b6
0000030: 004d b600 53b6 0057 b200 5cb2 005c b600
0000040: 60b2 005c b600 60b6 0064 b600 6aa7 004b
0000050: 57b2 0028 b200 2db6 0031 b200 3604 bd00
0000060: 3859 03b2 003b b200 2d12 3db6 0041 126c
0000070: b600 4753 c000 49b6 004d b600 53b6 0057
0000080: b200 5cb2 005c b600 60b2 005c b600 60b6
0000090: 0064 b600 6aa7 0003 b600 72b6 0076 1278
00000a0: b600 76b6 007b 4db2 002d 2cb6 007f b1
Exception Handler Table:
bci [9, 77] => handler: 80
Stackmap Table:
same_locals_1_stack_item_extended(@80,Object[#29])
full_frame(@152,{Object[#2],Object[#132]},{Object[#4],Object[#110]})
at BadScalac.main(BadScalac.scala)
But it goes away when I rewrite the source code as
import spray.json.DefaultJsonProtocol._
import spray.json._
object BadScalac extends App {
val msg = (
try Map("block" -> "try").toJson
catch { case _: Throwable => Map("block" -> "catch").toJson }
).prettyPrint + "\n"
println(msg)
}
or even when I drop the last addition of the "\n" string:
object BadScalac {
def main(args: Array[String]): Unit = {
val msg = (
try Map("block" -> "try").toJson
catch { case _: Throwable => Map("block" -> "catch").toJson }
).prettyPrint
println(msg)
}
}
The both snippets above yield
{
"block": "try"
}
with and without the last newline respectively.