Skip to content

java.lang.VerifyError: Bad type on operand stack #12557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xuwei-k opened this issue May 21, 2021 · 2 comments · Fixed by #12567
Closed

java.lang.VerifyError: Bad type on operand stack #12557

xuwei-k opened this issue May 21, 2021 · 2 comments · Fixed by #12567
Milestone

Comments

@xuwei-k
Copy link
Contributor

xuwei-k commented May 21, 2021

Compiler version

3.0.1-RC1-bin-20210521-de319fb-NIGHTLY and 3.0.0

Minimized code

package example

abstract class X[P <: Product](using val m: scala.deriving.Mirror.ProductOf[P]) {
  def unapply(p: P): m.MirroredElemTypes = ???
}

case class A(a: Int)
object A extends X[A]

object Main {
  def main(args: Array[String]): Unit = {
    A.unapply(A(2))
  }
}

Output

[info] running example.Main 
[error] (run-main-7) java.lang.VerifyError: Bad type on operand stack
[error] Exception Details:
[error]   Location:
[error]     example/A$.<init>()V @2: invokevirtual
[error]   Reason:
[error]     Type uninitializedThis (current frame, stack[1]) is not assignable to 'example/A$'
[error]   Current Frame:
[error]     bci: @2
[error]     flags: { flagThisUninit }
[error]     locals: { uninitializedThis }
[error]     stack: { uninitializedThis, uninitializedThis }
[error]   Bytecode:
[error]     0x0000000: 2a2a b600 15b7 0018 b1                 
[error] java.lang.VerifyError: Bad type on operand stack
[error] Exception Details:
[error]   Location:
[error]     example/A$.<init>()V @2: invokevirtual
[error]   Reason:
[error]     Type uninitializedThis (current frame, stack[1]) is not assignable to 'example/A$'
[error]   Current Frame:
[error]     bci: @2
[error]     flags: { flagThisUninit }
[error]     locals: { uninitializedThis }
[error]     stack: { uninitializedThis, uninitializedThis }
[error]   Bytecode:
[error]     0x0000000: 2a2a b600 15b7 0018 b1                 
[error] 
[error] 	at example.Main$.main(A.scala:11)
[error] 	at example.Main.main(A.scala)
[error] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] 	at java.lang.reflect.Method.invoke(Method.java:498)
[error] stack trace is suppressed; run last Compile / bgRun for the full output
[error] Nonzero exit code: 1
[error] (Compile / run) Nonzero exit code: 1

Expectation

@xuwei-k
Copy link
Contributor Author

xuwei-k commented May 21, 2021

#11208 same issue? 🤔

odersky added a commit to dotty-staging/dotty that referenced this issue May 22, 2021
odersky added a commit to dotty-staging/dotty that referenced this issue May 23, 2021
@Kordyjan Kordyjan added this to the 3.0.1 milestone Aug 2, 2023
@jim-mccabe
Copy link

I just experienced something similar on 3.3.3.

In my case, we have a server endpoint which returns some standard fields along with a legacy deprecated field. We instantiate an object and Jackson converts it into JSON.

To blend the standard & deprecated fields, we're using a trick where they are separate classes. Here's a simplified example:

case class InspectionDto(id: UUID, targetId: UUID)

trait DeprecatedInspectionFields {
  val fileId: UUID
}

This pattern has some benefits in our corporate codebase.

With Jackson, the resulting JSON produced by our API would successfully include the good + obsolete fields if we instantiated an anonymous class like this:

new InspectionDto(inspectionId, targetId) with DeprecatedInspectionFields {
  override val fileId = targetId
}

This worked well in 2.12 and 2.13, but in 3.3.3 at runtime we observed this:

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    com/porch/inspection/resource/InspectionResource$$anon$6.<init>(Lcom/porch/inspection/domain/manager/HydratedInspection;Lcom/porch/inspection/resource/InspectionResource;)V @135: getfield
  Reason:
    Type uninitializedThis (current frame, stack[0]) is not assignable to 'com/porch/inspection/resource/InspectionResource$$anon$6'
  Current Frame:
    bci: @135
    flags: { flagThisUninit }
    locals: { uninitializedThis, 'com/porch/inspection/domain/manager/HydratedInspection', 'com/porch/inspection/resource/InspectionResource', 'java/lang/Long', 'java/lang/Long', 'java/lang/Long', 'com/porch/dropwizard/api/dates/ApiCalendarDate', 'com/porch/inspection/dto/InspectionCompanyDto', 'java/lang/Long', 'java/util/UUID', 'java/net/URI' }
    stack: { uninitializedThis }
  Bytecode:
    0x0000000: 2cc7 000b bb00 2a59 b700 2dbf 2a2c b500
    0x0000010: 2fb2 0035 2bb6 003b b600 41b6 0045 b600
    0x0000020: 494e 2b2d b800 4d3a 04b2 0035 2bb6 003b
    0x0000030: b600 51b6 0052 b600 493a 052b 2d19 0419
    0x0000040: 05b8 0056 3a06 2c2b b600 3bb6 005a b600
    0x0000050: 5e3a 072b 2d19 0419 0519 0619 07b8 0062
    0x0000060: 3a08 2b2d 1904 1905 1906 1907 1908 b800
    0x0000070: 663a 092b 2d19 0419 0519 0619 0719 0819
    0x0000080: 09b8 006a 3a0a 2ab4 002f 2b2d 1904 1905
    0x0000090: 1906 1907 1908 1909 190a b600 6e3a 0b2a
    0x00000a0: b400 2f2b 2d19 0419 0519 0619 0719 0819
    0x00000b0: 0919 0a19 0bb6 0072 3a0c 2ab4 002f 2b2d
    0x00000c0: 1904 1905 1906 1907 1908 1909 190a 190b
    0x00000d0: 190c b600 763a 0d2a 2bb6 003b b600 7ab6
    0x00000e0: 007d 2d19 0419 0519 0619 0719 0819 0919
    0x00000f0: 0a19 0b19 0c19 0d2b b600 3bb6 0081 b700
    0x0000100: 842b b600 88ba 009d 0000 b600 a33a 0e2a
    0x0000110: 2bb6 00a6 ba00 ab00 00b6 00a3 b500 ad2a
    0x0000120: 190e 2aba 00b7 0000 b600 bbba 00c2 0000
    0x0000130: b600 c5b2 00ca b600 ceb6 00d2 c000 d4b5
    0x0000140: 00d6 b1                                
  Stackmap Table:
    same_frame(@12)

  at com.porch.inspection.resource.InspectionResource.toInspectionDto(InspectionResource.scala:167)

That final line number (167) is where we're instantiating this value, specifically the final close-brace of the anonymous class.

The problem would not arise if we stop using this anonymous class trick for the deprecated fields, and instead just instantiated a concrete class.

But the interesting thing is that it could be fixed in another way, which retains the class + trait trick! If we simply move the function which creates this result into an object, then the bug would not be triggered, and everything was fine again.

In the original code, we have a class InspectionResource which handles the inbound API calls. If we instantiate the anonymous class there, it breaks at runtime in 3.3.3.

By moving the new InspectionDto(...) with DeprecatedInspectionFields into a function in the companion object, the problem disappears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants